Transcript
Page 1: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Профилирование и оптимизация jQuery–кода

Владимир Журавлев

Page 2: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Самый популярный фреймворк*

* По данным builtwith.com

Page 3: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Все любят jQuery• Простота и более низкий порог вхождения;• кроссбраузерный фасад для рутинных операций;• наличие плагинов практически на все случаи жизни.

Page 4: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 5: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 6: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 7: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

•loop flipping;•array-push-join вместо сложения строк;•loop unrolling;•{'Вася': 1, 'Коля': 1}[name]•~~ (0.5 + n)

Page 8: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Преждевременная оптимизация

Page 9: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Преждевременная оптимизация

Симптомы:•оптимизация кода еще до того как он начнет тормозить.

Последствия:•потеря времени;•ухудшение читаемости.

Page 10: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Экономия на спичках

Page 11: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Экономия на спичкахСимптомы:•оптимизация частей кода, принципиально не влияющего на производительность;•автоматическое использование «оптимальных» конструкций.

Последствия:•потеря времени; •потеря читабельности;•легко упустить настоящую оптимизацию.

Page 12: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Профилирование

Page 13: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Как измерять?

• Таймеры (например, сonsole.time);• профилирование JS (Firebug, Web Inspector, YUI Profiler);• анализ timeline (Web Inspector).

Page 14: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

ТаймерыЗачем:•убедиться, что данный блок кода тормозит;•постоянно мониторить производительность модулей;•быстро оценить успешность оптимизации.

Чем замерять:•сonsole.time;•любой самописный таймер.

Page 15: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

сonsole.timeИспользование

console.time('init');

/* блок измеряемого кода */

console.timeEnd('init');

Page 16: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Профилирование JSЗачем:•для получения полного отчета о том на что тратит время ваш js код.

Чем профилировать:•console.profile; •YUI profiler;•любой другой самописный профайлер.

Page 17: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

console.profileДостоинства:•есть в Firefox, Chrome, Safari, IE 8+;•достаточный минимум.

Недостатки:•много шума при профилировании jQuery-кода;•разные форматы отчетов.

Page 18: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

console.profileИспользование

console.profile('init');

/* блок измеряемого кода */

console.profileEnd('init');

Page 19: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 20: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 21: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 22: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 23: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

YUI ProfilerЗачем:•для браузеров, в которых нет профайлера;•чтобы профилировать только обращения к jQuery; •для мониторинга производительности модулей.

developer.yahoo.com/yui/profiler

Page 24: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

YUI ProfilerИспользование:

YAHOO.tool.Profiler.registerFunction('init', window);

// профилируемый код

init();

var report = YAHOO.tool.Profiler.getFunctionReport('init');

YAHOO.tool.Profiler.unregisterFunction('init');

Page 25: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

YUI ProfilerДостоинства:•работает везде;•хорошо подходит для профилирования jQuery (например, можно логировать только $.fn.*, $.*).

Недостатки:•нельзя отличить $(selector) от $(html), $(element), $(function);•логирует вложенные вызовы, что может искажать статистику;•нет own time, только total time.

Page 26: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

jquery.profile.jsЗачем:•потому что велосипеды — это здорово;•чтобы избавиться от недостатков YUI Profiler.

Плюсы:•не логирует вложенные вызовы;•раздельно логирует $(selector), $(html), $(function) и $(element).

github.com/private-face/jquery.profile

Page 27: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

jquery.profile.jsИспользование:

var profiler = new $.Profiler;

profiler.start();

init();

profiler.stop();

profiler.topTime();

Page 28: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 29: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

jquery.profile.jsНедостатки:•не логирует вложенные вызовы;•«beta than nothing».

Page 30: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Анализ timelineЗачем:•чтобы определить как рендеринг влияет на производительность.

Что использовать:•Chrome Web Inspector.

Page 31: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 32: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Оптимизация

Page 33: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

$('div').click(function() {var div = $(this);

// ...});

$('div').each(function() {var div = $(this);

// ...});

Page 34: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Селекторы

Симптомы:•Большое число обращений к $(selector), $.fn.find, и т.п.;•Некоторые выборки выполняются довольно долго.

Page 35: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

1. Селекторы разбираются cправа-налево

$('div.post a.vote-up') // плохо

$('.post .vote-up'); // лучше

$('.vote-up'); // еще лучше

Page 36: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

2. Сужайте область поиска•Задавайте контекст

$('div.post a.vote-up'); // плохо$('#content').find('.vote-up'); // хорошо

•Используйте children, closest и т.п.

$('ul#list').find('li'); // плохо$('ul#list').children('li'); // хорошо

$('li').parents('div').first(); // плохо$('li').closest('div'); // хорошо

Page 37: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

3. Кешируйте выборки и используйте chaining

$('div.post').mousemove(function() ...);$('div.post').find('a').click(function() ...); // плохо

var posts = $('div.post');posts.mousemove(function() ...);posts.find('a').click(function() ...); // хорошо

$('div.post').mousemove(function() ...).find('a').click(function() ...).end().find('.invisible').hide(); // тоже хорошо

Page 38: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

4. Делегируйте обработку событий•Избавьтесь от live. Совсем.

$('a').live('click', function() {... // плохо

$(document).on('click', 'a', function() {... // супер

•Замените bind на on/delegate

$('.vote').click(function() {... // плохо

$('#content').on('click', '.vote', function() {... // хорошо

Page 39: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Слишком много on/delegateСимптомы:•задержка между событием и реакцией на него;•большое количество вызовов $.fn.is в профайлере.

Оптимизация:•отсекать лишние on/delegate;

•использование bind вместо on/delegate.

Page 40: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Повторяющиеся событияСимптомы:•«тормоза» в момент ресайза, скролла или интенсивного ввода текста;•профайлер показывает большое количество вызовов обработчиков событий keydown, scroll, resize и т.п.

Оптимизация:•Группировка нескольких вызовов события в один путем применения декораторов debounce и throttle. benalman.com/projects/jquery-throttle-debounce-plugin/

Page 41: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

debounce$.debounce•Группирует повторяющиеся события интервал между которыми меньше определенного значения.

события:

обработчик:

Page 42: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

throttle$.throttle•Группирует события которые были вызваны в пределах одного интервала.

события:

обработчик:

Page 43: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Оптимизация $(element)Симптом: •профайлер показывает существенную трату времени на $(element).

Оптимизация:•использовать один общий jQuery–объект для всех элементов внутри each/map;•quickEach.

Page 44: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

// создаем общий jQuery-объект за пределами map/each:var a = $([0]);

$('a').each(function() {// подставляем текущий элемент в объектa[0] = this;

// и используем его как обычный $(this)// ...

});

Page 45: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Недостаток:•Нельзя использовать во вложенных асинхронных функциях.

var a = $([0]);

$('a').each(function() {a[0] = this;

a.click(function() { // всегда будет выводиться текст последней ссылки alert(a.text());});

});

Page 46: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Оптимизация создания элементовСимптом:•профайлер показывает, что много времени уходит на $(html), append,

prepend, before, after и т.п.

Page 47: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

1. Клонирование быстрее создания// созданиеvar soldiers = $.map(names, function(name) {

return $('<div class="soldier"><span>' + name + '</span></div>');});

// клонированиеvar bobaFett = $('<div class="soldier"><span>Boba</span></div>');var name = bobaFett.find('span');

var soldiers = $.each(names, function(name) {name.text(name);return bobaFett.clone();

});

Page 48: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

2. Минимизируйте число операций вставки в DOM// вставка сразу после создания$.each(messages, function(_, text) {

$('#history').append('<div class="message">' + text + '</div>');});

// вставка пакетомvar fragment = $(document.createDocumentFragment());

$.each(messages, function(_, text) {fragment.append('<div class="message">' + text + '</div>');

});$('#history').append(fragment);

Page 49: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Restyle, layout, paintRestyle:•пересчет стилей не меняющих геометрию объектов.Layout:•пересчет геометрии.Paint:•перерисовка после пересчета свойств и геометрии.

Page 50: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Restyle, layout, paint• Изменения откладываются на потом;• иногда браузер вынужден применить изменения досрочно:

– offsetTop/Left/Width/Height– scrollTop/Left/Width/Height– clientTop/Left/Width/Height– getComputedStyle(), currentStyle [IE]

• время restyle, layout, paint сильно зависит от разметки.

jQuery.fn.css

Page 51: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

$('div').click(function() { var e = $(this);

e.css('color', e.css('backgroundColor'));

e.css('width', 100);

e.css('font-size', 20);

return false;});

Page 52: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

$('div').click(function() { var e = $(this);

e.css('width', 100);

e.css('color', e.css('backgroundColor'));

e.css('font-size', 20);

return false;});

Page 53: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 54: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Оптимизация .css• Проводить операции с элементами с display: none, либо до вставки в

документ;• заменить несколько css на add/removeClass;• группировать запросы CSS-свойств в начале функции (когда очередь

restyle и layout пуста);• не чередовать запросы и установку CSS у элемента.

Page 55: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Инициализация по требованиюПоказания к применению:•При загрузке страницы одновременно инициализируются множество одинаковых контролов (модулей, плагинов).

Оптимизация:•Инициализировать каждый контрол в момент первого обращения к нему.

Page 56: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

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

Оптимизация:•Откладывать трудоемкие итерации через setTimeout.

Page 57: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Общие рекомендации• Кешируйте все, что может пригодиться;• отсекайте лишние выборки, инициализацию плагинов и модулей, на

страницах, на которых они точно не нужны;• медленный JavaScript — далеко не единственная и не всегда главная

причина «тормозов» на сайте;• не бойтесь пересматривать требования.

Page 58: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)
Page 59: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)

Владимир ЖуравлевEvil Martians

[email protected]

github.com/private-face

@private_face

Page 60: Профилирование и оптимизация jQuery–кода (Владимир Журавлёв)