• Краткий экскурс в профайлинг JS

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

    Внёс изменения. Поставил таймер на mouseOver. Получается, что функция calculateSize выполняется 20-23ms. До этого примерно так и было.

    Нужно не таймером, а профайлером замерять (есть в Firebug и последних версиях Webkit).

    Ну я имею в виду функцию FireBug’а console.time() и console.timeEnd(). Они делают то же, что профайлер, только для определенного куска кода.

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

    Я просто не могу понять в этом профайлере где именно тормозит. Там всё исписано в init() :)

    Вот смотри, сейчас профайлер тебе говорит, что во время работы твоего эффекта больше всего ресурсов жрет функция init() из jQuery, которая вызывается почти 6000 раз:

    firebug1

    Так как сама по себе эта информация нам мало полезна, тебе нужно найти ту функцию, которая так часто вызывает init(). Для этого отсортируем данные по колонке Time (общее время выполнения функции). Видим, что на первом и втором месте стоит jQuery-функция, а на 3 и 4 — функции calculateSize() и imgSize(), время выполнения которых — 588 и 547 мс соответcтвенно.

    firebug2

    Тут явно видно, что сами эти функции выполняются очень быстро (см. Own Time), но вот они вызывают другие функции, которые и дают те самые 588 и 547 мс.

    Смотрим calculateSize(), проблемные места:

    var prevImg = slctdImg.parent().prevAll();
    var nextImg = slctdImg.parent().nextAll();
    

    Это все выборки по дереву, очень тяжелые операции.

    Смотрим imgSize(), проблемные места:

    imgCont.width(newWidth).height(newHeight);
    imgCont.css({
    	width: newWidth,
    	height: newHeight,
    	margin: (!dir) ? "0 0 " + k + "px 0" : k + "px 0 0 0",
    	zIndex: count - num,
    	opacity: 1 - (num) / 30
    });
    

    два раза устанавливаешь width и height

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

    Метки: , , ,
  • Один комментарий

    1. Jeremy Sandman
      3 июня 2010

      Отличный подход, спасибо за статью.