войти зарегистрироваться

data:URI и производительность, или как замедлить Firefox в 10 (десять) раз

Собственно, из заголовка должно быть почти все понятно. Но картинка не очень в тему: на ней надо нарисовать Лису, ползущую вслед догоняющему IE.

Это пост является ответом на «За бугром», ибо нашлась пара свободных часов, и было, чем их занять.

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-формате, а не дать четкий алгоритм расчета, когда их можно использовать, а когда нет.

комментарии (48)

  • В тестах обычно указывают тестовую конфигурацию компа и софтварного окружения (вплоть до версий ОС, драйверов, софта), чтобы понимать насколько это окружение может влиять на тесты.
    • «Обычное» окружение: Celeron Duo 1,7 Ghz, Windows XP, 1 Gb RAM.
    • это в каких тестах такое указывается? :)
      • в дотошных.
      • как правило — в gayмерских.
  • Проверил некоторые из приведенных ссылок в опере 10.10, хроме 3 и фф 3.5.6
    местами хром быстрее, местами опера, фф чуток тормозит.
    но цифры примерно одинаковые 15-40 мс, различия между браузерами меньше чем 50% на каждом из тестов.

    В общем тормоза в фф больше чем на порядок не подтверждаю.
    • Все спасибо. Исправленные результаты перевыложены. Отличие в 5-10 раз между фоновыми картинками и data:URI.
  • Вот и у меня не получилось добиться таких же тормозов ФФ.

    Немного медленней конечно, но никак не в 10 раз.

    имхо притянуто за уши.
  • Имхо, нужно сочетать преимущества спрайтов и data:URI.

    Я сначала создаю 1-2 спрайта с маленькими картинками (до 5kb), а что не влазит в них делаю через data:URI. Таким образом я избегаю множества HTTP запросов к маленьким файлам и в то же время не пытаюсь запихать в спрайт все, что возможно, тем самым увеличивая его геометрические размеры.

    Картинки размером более 5kb при возможности загоняю в спрайт, либо оставляю как есть.

    На выходе получается CSS файл небольшого размера (за счет того, что там не хранятся картинки по 20kb), 1-2 спрайта с элементами оформления и 2-3 картинки, которые в спрайт не влезли и слишком велики, чтобы бросать их в data:URI.
  • Рендеринг, может, и тормозит, но экономия на сетевых соединениях будет существеннее. Ну и некая разгрузка сервера тоже в плюс.
    • На сетевом соединении экономия один раз — при первой загрузке. Рендеринг будет тормозить при каждом посещении страницы.
  • НЛО прилетело и опубликовало эту надпись здесь.
    • 50 и 10 фпс на глаз очень даже заметны. К тому же эти 80 мс прибавятся к другим задержкам, которые могут стать причиной ухода пользователя. Здесь каждые 50 мс важны.
      • НЛО прилетело и опубликовало эту надпись здесь.
  • а какую из десятых опер тестировали? так-как в операх 10, 10.10 и 10.50 от версии повышалась скорость работы, а в 10.50 новая библиотека рендеринга вообще.
  • >>на ней надо нарисовать Лису, ползущую вслед догоняющему IE
    Мой мозг взорвался пытавшись представить это.
  • data:URI позволяет сэкономить на числе HTTP запросов, то есть как минимум RTT, или 4 * RTT если устанавливается новый коннект.
    кроме того, не надо использовать их для крупных изображений — base64, как известно, увеличивает исходный размер на 25%.
    в общем, имхо data:URI длиной более чем ~1500 байт (Ethernet MTU) — это некорректное использование.
  • Хром забыли
    • НЛО прилетело и опубликовало эту надпись здесь.
      • Хром уже не самый быстрый.
        • НЛО прилетело и опубликовало эту надпись здесь.
          • Да, появление Opera 9.50 prealpha
            • НЛО прилетело и опубликовало эту надпись здесь.
              • Почему это должно быть шуткой? Можете взять любой тест и сравнить самостоятельно. Или прочитать любую статью о выходе этой версии в интернете.
                • Жень, я бы не стал так категорично говорить. Объективно не понятно, какой из них «самый быстрый браузер». Слишком они разные.
                  • Мы же говорим в контексте. Там где самым быстрым считался Хром сейчас более быстрой может считаться «Опера».
                • НЛО прилетело и опубликовало эту надпись здесь.
                  • Я знаю, что есть тесты, где «Опера» ещё проигрывает Хрому. Хром считался быстрым браузером из-за движка JS, именно по этому критерию он считался быстрейшим. Вот тут «Опера» его обошла.
                  • Кстати, вы взяли «Оперу» 10.50 или 9.50, а то я там выше ошибся.
                    • НЛО прилетело и опубликовало эту надпись здесь.
                      • SunSpider
                        • НЛО прилетело и опубликовало эту надпись здесь.
            • Opera 10.5.
              • Да, правда :)
                • Я не фанат Хрома или ФФ или Оперы или Сафари, но реально Опера даже prealfa не фига не быстрее Хрома =)
                  • У меня на компе стоит 18 разных браузеров. Я регулярно смотрю что-то под ними. И я вижу, что prealpha всё-таки субъективно быстрее последнего Хромиума.
                    • 18… ну вы коллекционер! А у меня стоит Хроме в качестве основного, дома на Ubuntu, на работе на Mac, и на Win, тож дома на 2-м компе… честно не заметил я что Опера быстрее. А вот когда я в Преальфе открыл 51-ну вкладку, то на 52-й она лягла. тупо вылетела. Хотя стоит отметить что 50+ вкладок для преальфы… впечатлило. Но скорости все равно не заметил!
                      • Версия для Linux может отличаться (что-то может быть просто отключено), кроме того на блоге «Оперы» написано, что на процессорах без SSE2 (пока) новый движок JS не использует JIT.
                        • … вы не внимательны, к сожалению… я написал что у меня 3 ОС под рукой. А я браузеры я привык тестить всегда на ощуп, потому как спайдеры и тюдю расчитаны на определенные действия, скажем тест Javascript? Но там то определенные потоки, без учета корявой верстки или награможденности Javascript или Ajax… вот и получается реальный тестинг браузера только в реальном использовании…

                          Я тестил 10.50 на Вин и Мак, версию для Linux Не нашел :( Но скорости, еще раз говорю, не наблюдал. Для в нете главное СКОРОСТЬ, и мне честно пофиг ФФ это или Опера… или что-то еще.

                          P.S. под Линукс вообще есть Мидори, достаточно быстрый и легкий браузер на WebKit
                          • Да, я уже невнимателен, засыпаю, честно сказать. Sry.
                            • :) млин а точно-то… спать пора а то завтра фиг встану… работать нада хоть и суббота =)
    • хром в калесах =)
      • Догадайтесь откуда он там.
        • лол, надо спать =)
  • Судя по результатам, время инициализации не столь интересно. Статья наталкивает на другую любопытную мысль: а как использование большого числа data:uri картинок влият на repaint при мало-мальски сложных эффектах?
    Жаль, что в браузерах нет FPS-счетчика :)
    • Так скоро будут покупать видеоускорители для интернета :)
  • >Когда-то давно существовали рекомендации против использования обычных картинок.
    >Рекомендовалось все в фоновых изображениях делать.
    Сорри, но эти рекомендации вытекают не из соображений оптимизации.
  • А что в бете ФФ 3.6? Она во всех аспектах шустрее.
Только авторизованные пользователи могут оставлять комментарии. Авторизуйтесь, пожалуйста.