• Техногрет
  • Производительность браузеров в зависимости от верстки

    HTML и CSSXSLTJavaScriptИзображенияСофтEtc
    Сергей Чикуенок

    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. Помните главное правило: оптимизировать нужно то, что требует оптимизации.