Собственно, из заголовка должно быть почти все понятно. Но картинка не очень в тему: на ней надо нарисовать Лису, ползущую вслед догоняющему IE.
Это пост является ответом на «За бугром», ибо нашлась пара свободных часов, и было, чем их занять.
UPD Был обнаружен плагин — Wappalyzer — который на порядок замедлял отображение data:URI в Firefox. Но даже с его отключением Firefox продолжает проигрывать почти всем браузерам.
Но все по порядку.
Несколько месяцев назад ко мне в скайп постучался какой-то американец (с русским именем вроде) и спросил, что я знаю про последние оптимизации от Yahoo! (ну, те, где они data:URI наконец внедрили) и особенно про производительность data:URI. Я сказал, что, наверное (поскольку data:URI — это картинка в base64), последние несколько медленнее работают, чем обычные фоновые картинки, и вроде как должны подтормаживать.
Я быстро собрал предварительное окружение и через полчаса выдал предварительные результаты: data:URI тормозят, но иногда — очень сильно тормозят. Мне самому такой расклад показался подозрительным, поэтому я задвинул идею до лучших времен. И вот они настали :)
Если совсем коротко, то корректно измерять рендеринг страницы в браузере — задача весьма и весьма непростая. В данном случае она решена в очень грубом приближении (которого хватает для общей оценки ситуации, но его больше особо нигде не применить). В начало страницы вставляем таймер, на событие
Отлично. В итоге у нас есть «локальная» страница (после первого запроса к странице закрывают вкладку с ней, открываем новую вкладку и открываем в ней исходную страницу: это создает необходимую «чистоту» для эксперимента), которая отображается в браузере с жесткого диска. После этого время рендеринга будет (на 99%) зависеть от особенностей браузера, а не от скорости получения ресурсов.
Дополнительно, естественно, все тесты прогонялись по 10 раз. 3-дельта выбросы не брались в расчет. В итоге общая точность не меньше 10% (т.е. все, скорее всего, погрешность 3-5%).
Когда-то давно существовали рекомендации против использования обычных картинок. Рекомендовалось все в фоновых изображениях делать. Это не так (результаты отображения закэшированной страницы в мс).
Как мы видим, «оторвался» только Chrome (Safari в расчет не брался из-за дико оптимизированных таймеров, которые срабатывают «слишком быстро»), но на фоне основных браузеров это незаметно.
Вывод: разницы по существу нет. Особенно, если брать в расчет суммарную рабочую область изображений в 670000 квадратных пикселей (дальше будет пояснено, почему это немного).
Едем дальше. Помним, что data:URI поддерживается только IE8, для IE6/7 нужно использовать mhtml. Дополнительно IE8 не поддерживает картинки, большие 24 Кб. Поэтому в таблице для IE результаты mhtml, для остальных — data:URI.
Уже здесь заметны «некоторые тормоза». Для Firefox рендеринг одних и тех же картинок обошелся вообще в 10 раз тяжелее. Но мы же рассматриваем применением этих техник для фоновых изображений? А для них:
Общая тенденция, как видим, сохраняется. Но это еще не все
Вывод: data:URI тормозит в Firefox, mhtml тормозит в IE.
Внимательные читатели уже давно заготовили вопрос: что же нам показывают одни и те же неправдоподобно большие картинки. На «реальных» же сайтах все по-другому! Спешу их разочаровать: CSS Sprites размером 1000 на 1000 пикселей (миллион квадратных пикселей) встречаются не так редко. В среднем, на каждом сайт 5-20% области страницы занимают фоновые изображения. На разрешении 1200х1024 это примерно от 60 до 250 тысяч квадратных пикселей (т.е. всего в 3-10 раз меньше исходных изображений).
Но чего там дело встало, давайте возьмем 80 различных изображений (общей площадью 160 тысяч пикселей) и посмотрим, как браузеры из отрисовывают. А вот так (IE8 использует data:URI):
Что-то напоминает, правда? Да, мы уменьшили суммарный размер изображений в 4 раза, но при увеличении числа объектов в 40 раз (с 2 до 80) ситуация, практически, повторилась. На реальных страницах несколько десятков, порой и пара сотен фоновых изображений. Т.е. наши тесты все ближе и ближе к реальности.
Вывод: медленный рендеринг base64 зависит не только от размера области, но и от числа объектов.
Но и тут опять имело место небольшое лукавство: ведь мы не знаем, как поведут себя браузеры, если увидят такое же количество обычных картинок на странице — как они будут «тормозить» в этом случае? С этой целью было собрано еще 2 идентичных окружения. Для каждого использовалось 2 различных изображений и 10 объектов, вырезающих из них фон.
Для IE6/7/8 можно экстраполировать результаты, полученные из mhtml-страниц, либо пересобрать окружения с mhtml фоновыми картинками. Но основные результаты можно сказать уже сейчас.
Берем статистику использования браузеров, множим доли браузеров на относительное ускорение при использовании CSS Sprites (т.е. фоновых картинок) против data:URI / mhtml-подхода. Получаем цифру в 100мс для нашей суммарной области в 5*670000 = 3,35 миллиона пикселей (и 10 объектов). Для «среднего» сайта с 50 объектами с фоновыми изображениями и 100 тысячами пикселей в суммарной области мы получим порядка 15мс задержки при отображении каждой страницы (не важно, какое количество ресурсов находится в кэше браузера, сетевые задержки уже отыграли свое). Если у нас будет несколько сотен объектов с фоновыми изображениями, и общая область в миллион пикселей (например, какой-либо сложный веб-интерфейс), то средняя задержка для пользователей может вырасти до полусекунды и более. Такие вот пироги.
Вывод: data:URI + mhtml может существенно тормозить.
Все было бы неплохо, если Firefox и IE позаботятся о быстром рендеринге страниц и смогут отображать base64-данные так же быстро, как и обычные картинки. В этом случае использование множества base64-изображений будет, в общем случае, не хуже, чем CSS Sprites. Сейчас же наиболее оптимальным выходом является предварительное использование CSS Sprites, а потом конвертации минимального числа изображений в base64-формат, таким образом все издержки будут сведены к минимуму.
P.S. Если кому-то уж очень не нравятся фотографии на тестовых страницах — скиньте, пожалуйста, ссылки на любые подходящие по размеру — заменю. Просто ничего больше под рукой не было :)
P.P.S. Все расчеты в данной заметке оценочные. Они призваны показать только «слабые места» изображений в base64-формате, а не дать четкий алгоритм расчета, когда их можно использовать, а когда нет.
Это пост является ответом на «За бугром», ибо нашлась пара свободных часов, и было, чем их занять.
UPD Был обнаружен плагин — Wappalyzer — который на порядок замедлял отображение data:URI в Firefox. Но даже с его отключением Firefox продолжает проигрывать почти всем браузерам.
Но все по порядку.
Предыстория
Несколько месяцев назад ко мне в скайп постучался какой-то американец (с русским именем вроде) и спросил, что я знаю про последние оптимизации от Yahoo! (ну, те, где они data:URI наконец внедрили) и особенно про производительность data:URI. Я сказал, что, наверное (поскольку data:URI — это картинка в base64), последние несколько медленнее работают, чем обычные фоновые картинки, и вроде как должны подтормаживать.
Я быстро собрал предварительное окружение и через полчаса выдал предварительные результаты: data:URI тормозят, но иногда — очень сильно тормозят. Мне самому такой расклад показался подозрительным, поэтому я задвинул идею до лучших времен. И вот они настали :)
Тестовое окружение
Если совсем коротко, то корректно измерять рендеринг страницы в браузере — задача весьма и весьма непростая. В данном случае она решена в очень грубом приближении (которого хватает для общей оценки ситуации, но его больше особо нигде не применить). В начало страницы вставляем таймер, на событие
onload
вешаем завершение отсчета времени. Работать весь механизм будет или на локальном компьютере (чтобы устранить сетевые задержки), или на сервере с жестким кэшированием (браузеры в ходе одной сессии не перезапрашивают ресурсы с заголовками условного кэширования: это проверено, может быть, выложу статью и на эту тему).Отлично. В итоге у нас есть «локальная» страница (после первого запроса к странице закрывают вкладку с ней, открываем новую вкладку и открываем в ней исходную страницу: это создает необходимую «чистоту» для эксперимента), которая отображается в браузере с жесткого диска. После этого время рендеринга будет (на 99%) зависеть от особенностей браузера, а не от скорости получения ресурсов.
Дополнительно, естественно, все тесты прогонялись по 10 раз. 3-дельта выбросы не брались в расчет. В итоге общая точность не меньше 10% (т.е. все, скорее всего, погрешность 3-5%).
Тест первый: картинки против фона
Когда-то давно существовали рекомендации против использования обычных картинок. Рекомендовалось все в фоновых изображениях делать. Это не так (результаты отображения закэшированной страницы в мс).
Тест | Chrome2 | Fx3.5 | Opera10 | IE8 | IE6/7 |
---|---|---|---|---|---|
«Чистые» картинки | 33 | 10 | 52 | 189 | 182 |
Фоновые картинки | 124 | 11 | 47 | 181 | 130 |
Как мы видим, «оторвался» только Chrome (Safari в расчет не брался из-за дико оптимизированных таймеров, которые срабатывают «слишком быстро»), но на фоне основных браузеров это незаметно.
Вывод: разницы по существу нет. Особенно, если брать в расчет суммарную рабочую область изображений в 670000 квадратных пикселей (дальше будет пояснено, почему это немного).
Тест второй: производительность data:URI / mhtml
Едем дальше. Помним, что data:URI поддерживается только IE8, для IE6/7 нужно использовать mhtml. Дополнительно IE8 не поддерживает картинки, большие 24 Кб. Поэтому в таблице для IE результаты mhtml, для остальных — data:URI.
Тест | Chrome2 | Fx3.5 | Opera10 | IE8 | IE6/7 |
---|---|---|---|---|---|
data:URI и mhtml | 56 | 162 | 70 | 225 | 442 |
Уже здесь заметны «некоторые тормоза». Для Firefox рендеринг одних и тех же картинок обошелся вообще в 10 раз тяжелее. Но мы же рассматриваем применением этих техник для фоновых изображений? А для них:
Тест | Chrome2 | Fx3.5 | Opera10 |
---|---|---|---|
фоновые картинки в data:URI | 83 | 155 | 69 |
Общая тенденция, как видим, сохраняется. Но это еще не все
Вывод: data:URI тормозит в Firefox, mhtml тормозит в IE.
Тест третий: производительность большого количества data:URI / mhtml
Внимательные читатели уже давно заготовили вопрос: что же нам показывают одни и те же неправдоподобно большие картинки. На «реальных» же сайтах все по-другому! Спешу их разочаровать: CSS Sprites размером 1000 на 1000 пикселей (миллион квадратных пикселей) встречаются не так редко. В среднем, на каждом сайт 5-20% области страницы занимают фоновые изображения. На разрешении 1200х1024 это примерно от 60 до 250 тысяч квадратных пикселей (т.е. всего в 3-10 раз меньше исходных изображений).
Но чего там дело встало, давайте возьмем 80 различных изображений (общей площадью 160 тысяч пикселей) и посмотрим, как браузеры из отрисовывают. А вот так (IE8 использует data:URI):
Тест | Chrome2 | Fx3.5 | Opera10 | IE8 |
---|---|---|---|---|
много картинок в data:URI | 65 | 105 | 85 | 99 |
Что-то напоминает, правда? Да, мы уменьшили суммарный размер изображений в 4 раза, но при увеличении числа объектов в 40 раз (с 2 до 80) ситуация, практически, повторилась. На реальных страницах несколько десятков, порой и пара сотен фоновых изображений. Т.е. наши тесты все ближе и ближе к реальности.
Вывод: медленный рендеринг base64 зависит не только от размера области, но и от числа объектов.
Тест четвертый: лицом к лицу лица не увидать
Но и тут опять имело место небольшое лукавство: ведь мы не знаем, как поведут себя браузеры, если увидят такое же количество обычных картинок на странице — как они будут «тормозить» в этом случае? С этой целью было собрано еще 2 идентичных окружения. Для каждого использовалось 2 различных изображений и 10 объектов, вырезающих из них фон.
Тест | Chrome2 | Fx3.5 | Opera10 | IE8 | IE6/7 |
---|---|---|---|---|---|
фоновые картинки | 124 | 24 | 63 | 166 | 131 |
фоновые картинки в data:URI | 41 | 140 | 73 | - | - |
Для IE6/7/8 можно экстраполировать результаты, полученные из mhtml-страниц, либо пересобрать окружения с mhtml фоновыми картинками. Но основные результаты можно сказать уже сейчас.
Берем статистику использования браузеров, множим доли браузеров на относительное ускорение при использовании CSS Sprites (т.е. фоновых картинок) против data:URI / mhtml-подхода. Получаем цифру в 100мс для нашей суммарной области в 5*670000 = 3,35 миллиона пикселей (и 10 объектов). Для «среднего» сайта с 50 объектами с фоновыми изображениями и 100 тысячами пикселей в суммарной области мы получим порядка 15мс задержки при отображении каждой страницы (не важно, какое количество ресурсов находится в кэше браузера, сетевые задержки уже отыграли свое). Если у нас будет несколько сотен объектов с фоновыми изображениями, и общая область в миллион пикселей (например, какой-либо сложный веб-интерфейс), то средняя задержка для пользователей может вырасти до полусекунды и более. Такие вот пироги.
Вывод: data:URI + mhtml может существенно тормозить.
Что делать?
Все было бы неплохо, если Firefox и IE позаботятся о быстром рендеринге страниц и смогут отображать base64-данные так же быстро, как и обычные картинки. В этом случае использование множества base64-изображений будет, в общем случае, не хуже, чем CSS Sprites. Сейчас же наиболее оптимальным выходом является предварительное использование CSS Sprites, а потом конвертации минимального числа изображений в base64-формат, таким образом все издержки будут сведены к минимуму.
P.S. Если кому-то уж очень не нравятся фотографии на тестовых страницах — скиньте, пожалуйста, ссылки на любые подходящие по размеру — заменю. Просто ничего больше под рукой не было :)
P.P.S. Все расчеты в данной заметке оценочные. Они призваны показать только «слабые места» изображений в base64-формате, а не дать четкий алгоритм расчета, когда их можно использовать, а когда нет.