Сергей Чикуенок

Производительность браузеров в зависимости от верстки 23 декабря 2008


Задача.

Продемонстрировать зависимость скорости работы приложения от верстки.

Ежедневно занимаясь созданием и «оживлением» сайтов, я начал замечать одну довольно неприятную особенность: один и тот же JavaScript-код работает с разной скоростью на разных сайтах. Причина столь странного явления была найдена довольно быстро: скорость работы скрипта напрямую зависела от того, как именно был сверстан сайт. Поиск решений возникших проблем был довольно увлекательным, но, к сожалению, результатами своих исследований я не мог поделиться с публикой по одной простой причине: все решения носили локальный характер. На каком-то сайте что-то тормозило, и если одну конструкцию заменить на другую, то все работало в два раза быстрее. При таком объяснении единственное, что может сделать читатель, — это только порадоваться за меня, так как практической пользы от предложенных решений для него будет мало. Это стало первой причиной, по которой я начал исследование общих проблемных мест в современных браузерах.

Вторая причина — это шумиха, возникающая вокруг новых версий браузеров. Думаю, ни для кого не секрет, что JS-код в браузерах работает довольно медленно (по сравнению, скажем, с такой же программой, написанной на C++). Разработчики осознали это сравнительно недавно и начали переписывать JS-движки своих продуктов для увеличения их производительности (V8 у Google Chrome, TraceMonkey у Firefox и так далее). В сети появилось множество тестов, которые измеряют производительность этих движков, одни из самых известных — SunSpider и Dromaeo. Тесты довольно качественные, но многие пользователи не обращают внимания, что это именно JavaScript Performance Test, а не Browser Performance Test. Я считаю, что их результаты далеко не объективны для современных веб-приложений. Можно ли однозначно утверждать, что один браузер будет быстрее другого во всех возможных случаях?

Рассмотрим пример. В Dromaeo есть такой тест как «работа со стилем DOM-элемента» (DOM Style). Я не буду подробно останавливаться на его реализации, скажу лишь, что он достает все div-элементы со страницы и пытается изменить у них свойства color и display (меня интересует именно модификация стиля). А что если поместить эти элементы в другое окружение (читай, иначе сверстать страницу)? Это уже другой результат. А если этим элементом будет не div, а картинка? Это уже третий результат. А если прописать определенные CSS-стили этим элементам? В общем, вы поняли :-)

В итоге получается, что производительность веб-приложения зависит не только от JS-движка, но и от движка браузера. Чтобы продемонстрировать это, я сделал несколько простых тестов.

Лирическое отступление

Ни в коем случае нельзя относиться к представленным примерам как к «еще одному тесту производительности браузеров». Их задача — всего лишь продемонстрировать зависимость скорости работы приложения от верстки.

Методика тестирования

  1. В сравниваемых примерах пользователь должен видеть один и тот же результат. То есть принимаем во внимание тот факт, что одну и ту же цель можно достичь разными способами.
  2. Во всех примерах используется простая JavaScript-анимация, результатом является количество кадров в секунду (FPS).
  3. Чем выше результат, тем лучше.
  4. В процессе тестирования очень сложно было получить одинаковый результат за несколько прогонов одного и того же теста в одном браузере. Поэтому за погрешность измерения я взял 3 FPS. То есть если результат одного теста отличается на ±3 FPS от другого, я считаю, что результаты равны.
  5. Все тесты прогонялись несколько раз, в качестве итогового значения брался средний результат этих прогонов.
  6. Тестовая машина: MacBook Pro @ 2.16 Ghz Intel Core 2 Duo, 2 GB RAM. Windows-браузеры проверялись в Parallels Desktop 3, разные версии IE были на разных виртуальных машинах.

Протестированные браузеры

Результаты

position: relative против position: absolute

Меня давно интересовал вопрос, что работает быстрее: элемент с position: relative или position: absolute?

Как видно из результатов, Opera — единственный браузер, у которого производительность зависит от того, как спозиционирован модифицируемый элемент.


position: relative против position: absolute с большим количеством элементов

В интернете очень часто можно встретить советы по сокращению количества элементов в DOM-дереве. В их пользу приводятся такие неуверенные аргументы, как «зачем замусоривать DOM?», «чем меньше элементов, тем быстрее загрузится сайт» и тому подобное.

Проверим, как это влияет на производительность. Для этого теста я обрамил каждое слово в контентном блоке span-элементом. В итоге суммарное количество DOM-элементов на странице — 942. Для сравнения:

Результат поиска в «Гугле» — 384 элемента

Результат поиска на Яндексе — 555

Главная страница Мейл.ру — 1196

Главная страница Ленты.ру — 2669


В данном тесте примеры сравнивались не друг с другом, а с первым тестом, так как нам нужно продемонстрировать влияние на производительность количества элементов, а не способа позиционирования.


position: relative

Этот тест
position: relative против position: absolute


position: absolute

Этот тест
position: relative против position: absolute


Что ж, малое количество элементов в DOM-дереве — это не только эстетика, но и заметный выигрыш в производительности у многих современных браузеров.

Хозяйке на заметку

Не стоит без надобности увеличивать количество элементов в дереве документа.

position: relative против position: absolute с большим количеством элементов, у которых указан border

Немного усложним предыдущий тест: добавим всем обрамляющим слова span-элементам CSS-свойство border: 1px solid #fff и посмотрим, как это повлияло на производительность. Помня о том, что пользователь должен видеть одинаковый результат во всех тестах, подавляем действие бордюра с помощью свойства margin: -1px.


position: relative

Этот тест
position: relative против position: absolute с большим количеством элементов


position: absolute

Этот тест
position: relative против position: absolute с большим количеством элементов


Если оценивать «на глазок», у Firefox заметны сильные провалы в производительности, хотя итоговый результат не сильно отличается от предыдущего теста.

Очень надеюсь, что ребята из Microsoft избавятся от такого провала производительности в финальной версии своего нового браузера.


Глубина DOM-дерева

По аналогии с тестом большого количества элементов проверим, влияет ли глубина дерева на производительность. Для этого я сделал структуру из 30 вложенных друг в друга элементов. В первом случае я обрамил весь макет этой структурой, а во втором — просто добавил эту структуру в самый конец макета (чтобы нормализовать количество элементов на странице). Чтобы появление этих элементов было хоть как-то оправдано (их ведь не просто так добавляют), я указал им CSS-стили: margin: -1px; padding: 1px; width: 100%;



Хозяйке на заметку

Неглубокое дерево выглядит эстетично и повышает производительность сайта.

Анимация полупрозрачной картинки

Что быстрее — непрозрачная картинка с CSS-свойством opacity или полупрозрачная картинка?

Из тестов IE6 был исключен намеренно: единственный способ показать полупрозрачную картинку — использовать фильтр AlphaImageLoader, который сам по себе повышает производительность анимации.




Определенно, анимация с полупрозрачной картинкой заметно плавнее в современных браузерах, чем анимация непрозрачной картинки со свойством opacity. Впечатляет прирост скорости у нового WebKit.

Несмотря на неплохой результат, анимация в Google Chrome работает довольно медленно.


Картинка против фонового изображения

Задача: поместить на фон изображение, поверх которого запускается анимация. Что будет работать быстрее: очевидное CSS-свойство background-image или img-элемент?



Как видно из примеров, очевидное для такой задачи использование background-image привело к серьезному падению производительности в Safari и Opera. Причем проблемы заметны именно на Mac-версиях браузеров.

Несмотря на высокий результат, анимация в Opera (Mac) выглядит очень неприятно (заметны сильные рывки).

На самом деле, в некоторых случаях img работает гораздо быстрее background-image и в Firefox (в данном тесте это не заметно).

Хозяйке на заметку

Использование img вместо background-image может заметно повысить производительность.

Растянутое изображение

Что будет, если фоновую картинку из предыдущего теста увеличить хотя бы на 1 пиксель в HTML?



Похоже, современные браузеры пока не умеют оптимизировать такие задачи и перерисовывают растянутое изображение каждый раз, когда что-то меняется на странице. Проблема появляется именно в тех браузерах, которые сглаживают растянутые изображения.

В Firefox 3 на больших картинках начинает заметно тормозить даже прокрутка страницы.

Хозяйке на заметку

В IE7 можно включить сглаживание картинок: -ms-interpolation-mode: nearest-neighbor | bicubic. Однако это снижает производительность IE7 примерно в 2 раза.

Заключение

Как видно из приведенных тестов, ситуация с современными браузерами далеко не однозначная. В завершении статьи я решил собрать вместе все советы, которые могут помочь с оптимизацией проекта.

  1. Для интерактивных элементов лучше использовать position: absolute.
  2. Большое количество элементов на странице может снизить производительность, но не стоит увлекаться их сокращением в ущерб надежности макета.
  3. Не надо делать очень глубоких вложенных структур элементов.
  4. Прежде чем начинать верстку макета, следует узнать, какие интерактивные механизмы там должны быть — это избавит от многих проблем уже на начальном этапе работы над проектом.
  5. Не надо загонять себя в угол глупых стереотипов: «валидность» и «семантичность» никому, кроме самих разработчиков, не нужна.
  6. Не стоит без надобности растягивать картинки. Если это необходимо сделать, следует воспользоваться canvas.
  7. Как правило, img-элемент будет работать гораздо быстрее, чем CSS-свойство background-image.
  8. Помните главное правило: оптимизировать нужно то, что требует оптимизации.