Опубликован: 16.06.2010 | Уровень: специалист | Доступ: платный
Лекция 7:

Технологии будущего

Аннотация: В этой лекции собрана часть материалов, затрагивающих передний край клиентских технологий и их производительность. В ней освещаются вопросы, связанные с профилированием JavaScript, проблемами в оценке производительности браузеров и скоростью работы CSS-селекторов в JavaScript-библиотеках. Во второй половине лекции затрагивается тема асинхронной (многопоточной) производительности на основе JavaScript и производительности AJAX при загрузке страницы.

6.1. Профилируем JavaScript

Данный раздел написан после прочтения ряда заметок Джона Реси-га (автора JavaScript-библиотеки jQuery), в которых он рассказывал про особенности работы JavaScript в различных браузерах.


После существенной оптимизации CSS-селекторов и выхода SizzLe (http://sizzLejs.com/), который лишь немного уступает YASS (http://yass.webo.in/), автор jQuery сконцентрировал свои усилия на оптимизации работы с DOM-деревом и наиболее используемых методов и начал искать дополнительные способы для профилирования и оптимизации.

Также было написано дополнение для глубокого профилирования (http://ejohn.org/blog/deep-profiling-jquery-apps/) jQuery — оно помогло обнаружить методы, которые выполняются чересчур долго на реальных сайтах с jQuery. Дальше было проведено уточнение самих оптимизационных методов, которые, очевидно, являются не такими эффективными, как нам хотелось бы, — ведь непонятно, где именно и что конкретно нужно оптимизировать.

Для ответа на этот вопрос можно пойти по известному пути и замерить число вызовов функции из какого-либо метода. В этом нам может помочь Firebug, который позволяет увидеть эту информацию в соответствующей вкладке (еще и наряду со значениями времени выполнения каждого метода). К несчастью, очень неудобно вручную вбивать код, затем проверять результаты в консоли и определять, насколько они неудовлетворительны и изменились ли они с прошлого раза. Если бы только существовал способ получать эти числа в автоматическом режиме!

6.1.1. Профилирующие методы FireUnit

Джон Ресиг немного улучшил описанную ситуацию и добавил пару новых методов в FireUnit (http://fireunit.org/).

fireunit.getProfile();

Можно запустить этот код сразу после того, как вы использовали console.profile() ; и console.profileEnd() ; для перехвата проблемного участка кода, — и получить полный вывод профилирующей информации. Например, если мы запустим это, то получим из fireunit.getProfile() следующий объект JavaScript:

{
  "time": 8.443,
  "calls": 611,
  "data":[
{
  "name":"makeArray()",
  "calls":1,
  "percent":23.58,
  "ownTime":1.991,
  "time":1.991,
  "avgTime":1.991,
  "minTime":1.991,
  "maxTime":1.991,
  "fileName":"jquery.js (line 2059)"
  },
// etc.
]}
fireunit.profile( fn );
Профилирование вызовов JavaScript, источник: ejohn.org

Рис. 6.1. Профилирование вызовов JavaScript, источник: ejohn.org

Второй метод, добавленный в FireUnit, позволяет достаточно просто запускать и профилировать отдельные вызовы функций. Грубо говоря, этот метод запускает профайлер, исполняет функцию, останавливает профайлер, а затем возвращает результаты из getProfile(). Дополнительно он проверяет возможные исключения при вызове функции и гарантирует, что профайлер надежно выключен.

Это можно использовать примерно следующим образом:

fireunit.profile(function(){
  document.getElementsByClassName("foo");
});

6.1.2. Как это все применять

Во-первых, обязательно нужно установить последнюю версию (http://github.com/jeresig/fireunit ) FireUnit. Также можно скачать последнюю версию кода в виде расширения к Firefox: http://fireunit.org/fireunit-1.0a1.xpi

При запуске нужно будет убедиться, что:

  1. обе вкладки Console и Script в Firebug включены;
  2. свойство extensions.firebug.throttleMessages в about:config выставлено в false.

6.1.3. Результаты

Ниже приведены результаты вызовов из jQuery 1.3.2 ("методом" называется метод jQuery, который запускается с определенными параметрами, "вызовы" — это число вызовов функции, которые происходят во время работы метода, "O(n)" является грубой оценкой сложности вызова функции):

Таблица 1.1. Тестовая таблица
Метод Вызовы O(n)
.addClass("test"); 542 6n
.addClass("test"); 592 6n
.removeClass("test"); 754 8n
.removeClass("test"); 610 6n
.css("color", "red"); 495 5n
.css({color: "red", border: "1px solid red"}); 887 9n
.remove(); 23772 2n+n 2
.append("

test

");
307 3 n
.append("<p>test</p><p>test</p> <p>test</p><p>test</p><p>test</p>"); 319 3n
.show(); 394 4n
.hide(); 394 4n
.html("<p>test</p>"); 28759 3n+n 2
.empty(); 28452 3n+n 2
.is("div"); 110
.filter("div"); 216 2n
.find("div"); 1564 16n

Как можно видеть из этой таблицы по значениям O(n), большинство методов jQuery вызывают по крайней мере по одной функции на каждый элемент, который им нужно обработать. addClass запускает около шести функций на каждый элемент, filter — примерно две, а is — только одну.

Также мы легко видим проблемные методы, напоминающие большие черные дыры, в которые утекает процессорное время — .remove(), .empty() и .html(). Все они имеют сложности с вызовом функций n 2 , что является значительной проблемой для производительности ваших сайтов. Все эти числа выросли по очень простой причине: .html() использует .empty(), .empty() использует .remove(), а .remove() работает крайне неэффективно. Если не начать профилировать вызовы функций на медленное выполнение (к слову сказать, большинство внутренних методов jQuery выполняются очень быстро), то и не удастся обнаружить код, написанный неэффективно.

После внесения необходимых изменений мы придем к значительно улучшенным числам:

Метод Вызовы O(n)
.remove(); 298 3n
.html("<p>test</p>"); 507 5n
.empty(); 200 2n

Автоматизированный процесс профилирования кода открывает широкие просторы для исследовательской деятельности. Даже не используя ничего другого, кроме вышеописанного метода, уже можно значительно улучшить каждый метод jQuery и любой другой клиентской библиотеки.

Также весьма интересно интегрировать описанное профилирование как часть самого процесса разработки — чтобы сразу замечать очевидные недочеты в производительности.

Позиция John относительно философии развития jQuery заслуживает отдельного слова. John изначально закладывается на совместимость со всеми браузерами, чтобы охватить максимальную аудиторию пользователей и разработчиков. И только после этого (когда стало понятно, что jQuery работает не так эффективно, как хотелось бы) он начал ее существенно оптимизировать. С точки зрения маркетинга — очень грамотный подход.

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

Данный раздел написан на основе статьи Christian Stockwell, отвечающего за производительность браузера IE. Измерение общей производительности веб-сайтов и браузеров крайне важно для большого числа людей: как для пользователей, использующих различные продукты, так и для разработчиков, оптимизирующих свои порталы. Также сами разработчики других браузеров внимательно следят за успехами их коллег по цеху и стараются ориентироваться на некоторые отраслевые стандарты качества.

6.2.1. Измерение производительности браузера

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


Наилучшие способы измерения производительности браузера должны непременно содержать сценарии, отражающие реальные ситуации, в которых он используется. Работа с реальными веб-сайтами позволяет учесть те факторы, которые в случае применения тестов, симулирующих какую-то ситуацию, учету не поддаются, и передать целостное впечатление о производительности. Однако тестирование браузеров на настоящих веб-ресурсах связано с рядом нюансов, и в этом разделе обсуждаются некоторые способы, которые применяются для адекватного измерения производительности IE.

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

Часть проблем оценки производительности вызвана огромным количеством разнообразных действий, для которых используется браузер. Каждый день пользователи обращаются к широкому диапазону ресурсов — от насыщенного мультимедийным содержимым FLickr до спартанского GoogLe. Они могут столкнуться с интерактивным, насыщенным AJAX-скриптами сайтом, как Windows Live HotmaiL, или сайтом, содержащим лишь статический HTML, как, например, CraigsList, а некоторые из них станут использовать браузер для критически важных деловых приложений (например, построенных на его основе систем электронного документооборота).

Производительность каждого из этих ресурсов часто зависит от производительности отдельной подсистемы браузера. Например, загрузка насыщенного изображениями сайта может зависеть от скорости, с какой браузер в состоянии загружать и распаковывать изображения. Напротив, производительность простенькой страницы зависит от того, как быстро браузер обрабатывает стандартный HTML. В следующем случае для хорошей производительности насыщенного AJAX-скриптами портала потребуется тесная интеграция JavaScript, CSS и DOM, — и это окажется в большей степени важным, нежели индивидуальная производительность каждого из названных компонентов. Когда на чашу весов кладутся FLash и SiLverLight, производительность будет зависеть от того, насколько хорошо встроены в браузер соответствующие подсистемы управления.

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

Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Галина Башкирова
Галина Башкирова

Здравствуйте, недавно закончила курс по проф веб программиованию, мне прислали методические указания с примерами тем, однако темы там для специальности 

Системный администратор информационно-коммуникационных» систем.
Мне нужно самой найти тему? или делать по высланным темам

 

Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург
Ёдгор Латипов
Ёдгор Латипов
Таджикистан, Кургантепа