Please note, this is a STATIC archive of website developer.mozilla.org from November 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

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

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

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Используйте средства профилирования, чтобы находить узкие места в своём JavaScript коде.  Профайлер периодически проверяет состояние стека вызовов JavaScript и составляет статистику на основе полученных в результате измерения величин.

Вы можете запустить профайлер выбрав «Profiler»  из меню «Web Develeper». Для операционных систем Linux и OS X данное меню находится в меню «Tools», в Windows его можно вызвать из меню «Firefox».

В открывшемся меню уже будет выбран профайлер.

 

Семплирующие профайлеры

 

Профайлер JavaScript — сэмплирующий профайлер. Это означает, что он периодически собирает информацию о состоянии интерпретатора JavaScript, сохраняет стек выполняющегося на момент сэмплирования кода. Статистически, число образцов полученных во время выполнения какой-либо функции, соответствует количеству времени, которое браузер проводит выполняя её, таким образом вы можете находить узкие места в своём коде.

Рассмотрим следующую программу в качестве примера:

function doSomething() {
  var x = getTheValue();
  x = x + 1;                   // -> sample A
  logTheValue(x);
}

function getTheValue() {
  return 5;
}

function logTheValue(x) {
 console.log(x);               // -> sample B, sample C
}

doSomething();

Допустим мы запустили данную программу с активным профайлером, и во время её выполнения, профайлер взял три сэмпла, в местах указанных комментариями.

Они все взяты внутри doSomething(), но вторые два внутри функции logTheValue() вызванной doSomething(). В результате получим профиль состоящий из трёх записей:

Sample A: doSomething()
Sample B: doSomething() > logTheValue()
Sample C: doSomething() > logTheValue()

Конечно этих данных недостаточно, чтобы сделать какие-то выводы, но с гораздо большим количеством сэмплов, мы поймём, что узким местом в нашей программе является logTheValue().

 

Создание профиля

Нажмите кнопку stopwatch в профайлере, чтобы начать сбор сэмплов. Кнопка stopwatch подсвечена, если профайлер активен. Кликните на ней ещё раз и сохраните новый профиль:

 

Новый профиль будет открыт автоматически при нажатии "Stop".

Панель разделена на две части:

  • Левая сторона содержит список всех записанных профилей и позволяет загрузить любой из них. Ниже находятся две кнопки: stopwatch позволяет записать новый профиль, в то время как import... позволяет импортировать ранее сохраненные данные. Когда профиль выбран, вы можете сохранить его данные как файл в формате JSON нажав на кнопке Save.
  • Правая сторона показывает текущий загруженный профиль.

 

Анализируем профиль

 

Профиль разделён на две части:

График профилирования

График профилирования располагается в верхней части экрана профиля.

Горизонтальная ось это время, а вертикальная — размер стека вызовов на текущий сэмпл. Стек вызовов представляет количество активных функций  на момент сэмплирования.
Красные сэмплы на графике говорят о том, что браузер был недоступен на тот момент и пользователь мог наблюдать паузы в анимации и отклике браузера. Если профиль содержит красные образцы,  их следует разбить на несколько событий и рассмотреть  используя requestAnimationFrame и Workers.

Подсветив определённый участок в профиле рамкой, можно исследовать его более детально:

В таком случае, над графиком появится новая кнопка с надписью вида: "Sample Range [AAA, BBB]". Нажав на неё, можно приблизить рассматриваемый участок и детально его рассмотреть.

Детали профилирования

Детали профилирования расположены в нижней части экрана профиля:

Когда вы впервые открываете новый сэмпл, панель сэмплов содержит единственную строку «(total)»,  как на скриншоте ниже. Если кликнуть на стрелке следующей за надписью «(total)», вы увидилте список всех функций верхнего уровня которые находятся в сэмпле.


Время выполнения (Running time) показывает число сэмплов в которых присутствует данная функция1 , далее следует процент появления функции в остальных сэмплах профиля.  Первая сверху строка показывает, что в профиле 2021 сэмпл, вторая строка показывает, что 1914 или 94.7% из них содержат в себе функцию detectImage().

Self показывает количество сэмплов полученное во время выполнения самой функции, а не функции её вызвавшей. В примере выше  doSomething() имеет время выполнения (Running time) равное 3 (сэмпл A, B и C), но значение Self равно единице (sample A).

Третий столбец содержит имена функций, а также имена файлов и номера строк (для локальных функций) или полное/доменное имя (для внешних). Функции серого цвета — встроенные функции браузера, чёрные — JavaScript загруженный страницей. Если вы переместите курсор мыши вдоль строк, то обнаружите справа от имён функций стрелочку: кликните по ней и увидите исходный код функции.

 

Раскрываем древо вызовов

 

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

Для примера приведённого выше, полностью раскрытое древо вызовов будет выглядеть следующим образом:

Running Time Self  
3            100% 1 doSomething()
2              67% 2 logTheValue()

Более реалистичный пример: на скриншоте ниже,  на второй строке видно 1914 сэмпла взятых внутри функции detectImage(). Но все сэмплы были получены  внутри функции названной detectImage() (Self равно нулю). Мы можем развернуть древо вызовов чтобы определить какая из функций на самом деле выполнялась когда было взято большинство сэмплов:

Далее можно сделать вывод, что 6 сэмплов было взято во время выполнения detectAtScale(), 12 во время getRect() и так далее.

Примечания

  1.   Если функция вызывается несколько раз из различных источников, в выводе профайлера представлена она будет так же несколько раз. Так структуры вроде forEach будут появляться несколько раз в древе вызовов.

     

 

Метки документа и участники

 Внесли вклад в эту страницу: CamelFoe
 Обновлялась последний раз: CamelFoe,