aboutsummaryrefslogtreecommitdiff
path: root/files/ru/tools/profiler/index.html
blob: 2d3de16835de6cdb5f2f8729620112411b236d12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
---
title: Профилирование JavaScript
slug: Tools/Profiler
tags:
  - Firefox
  - Отладка
  - Профайлер
  - Профилирование
  - Руководство
  - инструменты
translation_of: Tools/Performance
---
<div>{{ToolsSidebar}}</div><p>Используйте средства профилирования, чтобы находить узкие места в своём JavaScript коде.  Профайлер периодически проверяет состояние стека вызовов JavaScript и составляет статистику на основе полученных в результате измерения величин.</p>

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

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

<p> </p>

<h2 id="Семплирующие_профайлеры"><a name="sampling-profilers">Семплирующие профайлеры</a></h2>

<p> </p>

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

<p><a name="profiling-example">Рассмотрим следующую программу в качестве примера:</a></p>

<pre class="brush: js">function doSomething() {
  var x = getTheValue();
  x = x + 1;                   // -&gt; sample A
  logTheValue(x);
}

function getTheValue() {
  return 5;
}

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

doSomething();</pre>

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

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

<pre>Sample A: doSomething()
Sample B: doSomething() &gt; logTheValue()
Sample C: doSomething() &gt; logTheValue()</pre>

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

<p> </p>

<h2 id="Создание_профиля">Создание профиля</h2>

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

<p> </p>

<p style="text-align: center;"><img alt="" src="https://mdn.mozillademos.org/files/5977/Screen%20Shot%202013-08-26%20at%2010.35.47%20AM.png"></p>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5981/Screen%20Shot%202013-08-26%20at%2011.07.18%20AM.png" style="display: block; margin-left: auto; margin-right: auto;"></p>

<p>Панель разделена на две части:</p>

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

<p> </p>

<h2 id="Анализируем_профиль">Анализируем профиль</h2>

<p> </p>

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

<ul>
 <li><a href="#profile-timeline" title="#profile-timeline">График профилирования (profile timeline</a>)</li>
 <li><a href="#profile-details" title="#profile-details">Детали профилирования (profile details</a>)</li>
</ul>

<h3 id="График_профилирования"><a id="profile-timeline" name="profile-timeline">График профилирования</a></h3>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5987/timeline" style="display: block; margin-left: auto; margin-right: auto;"></p>

<p>Горизонтальная ось это время, а вертикальная — размер стека вызовов на текущий сэмпл. Стек вызовов представляет количество активных функций  на момент сэмплирования.<br>
 Красные сэмплы на графике говорят о том, что браузер был недоступен на тот момент и пользователь мог наблюдать паузы в анимации и отклике браузера. Если профиль содержит красные образцы,  их следует разбить на несколько событий и рассмотреть  используя <a href="/en-US/docs/Web/API/window.requestAnimationFrame" title="/en-US/docs/Web/API/window.requestAnimationFrame">requestAnimationFrame</a> и <a href="/en-US/docs/Web/Guide/Performance/Using_web_workers" title="/en-US/docs/Web/Guide/Performance/Using_web_workers">Workers</a>.</p>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5989/Screen%20Shot%202013-08-26%20at%2011.17.59%20AM.png" style="display: block; margin-left: auto; margin-right: auto;"></p>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5991/Screen%20Shot%202013-08-26%20at%2011.18.03%20AM.png" style="display: block; margin-left: auto; margin-right: auto;"></p>

<h3 id="Детали_профилирования"><a name="profile-details">Детали профилирования</a></h3>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5993/profiler-details-highligted.png" style="display: block; margin-left: auto; margin-right: auto;"></p>

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

<p><br>
 <img alt="" src="https://mdn.mozillademos.org/files/5995/Screen%20Shot%202013-08-26%20at%2011.22.10%20AM.png"></p>

<p>Время выполнения (<strong>Running time</strong>) показывает число сэмплов в которых присутствует данная функция<a href="#footnote-1"><sup>1</sup></a> , далее следует процент появления функции в остальных сэмплах профиля.  Первая сверху строка показывает, что в профиле 2021 сэмпл, вторая строка показывает, что 1914 или 94.7% из них содержат в себе функцию detectImage().</p>

<p><strong>Self</strong> показывает количество сэмплов полученное во время выполнения самой функции, а не функции её вызвавшей. В <a href="#profiling-example" title="#profiling-example">примере</a> выше  doSomething() имеет время выполнения (<strong>Running time</strong>) равное 3 (сэмпл A, B и C), но значение <strong>Self</strong> равно единице (sample A).</p>

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

<p> </p>

<h3 id="Раскрываем_древо_вызовов">Раскрываем древо вызовов</h3>

<p> </p>

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

<p>Для <a href="#profiling-example" title="#profiling-example">примера</a> приведённого выше, полностью раскрытое древо вызовов будет выглядеть следующим образом:</p>

<table class="standard-table">
 <tbody>
  <tr>
   <td style="text-align: center;"><strong>Running Time</strong></td>
   <td style="text-align: center;"><strong>Self</strong></td>
   <td style="text-align: center;"> </td>
  </tr>
  <tr>
   <td style="text-align: center;">3            100%</td>
   <td style="text-align: center;">1</td>
   <td style="text-align: center;">doSomething()</td>
  </tr>
  <tr>
   <td style="text-align: center;">2              67%</td>
   <td style="text-align: center;">2</td>
   <td style="text-align: center;">logTheValue()</td>
  </tr>
 </tbody>
</table>

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

<p><img alt="" src="https://mdn.mozillademos.org/files/5999/bla.png" style="display: block; margin-left: auto; margin-right: auto;"></p>

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

<p>Примечания</p>

<ol>
 <li><a name="footnote-1">  </a>Если функция вызывается несколько раз из различных источников, в выводе профайлера представлена она будет так же несколько раз. Так структуры вроде forEach будут появляться несколько раз в древе вызовов.

  <p> </p>
 </li>
</ol>

<p> </p>