diff options
Diffstat (limited to 'files/ja/conflicting/tools/performance')
-rw-r--r-- | files/ja/conflicting/tools/performance/call_tree/index.html | 114 | ||||
-rw-r--r-- | files/ja/conflicting/tools/performance/index.html | 145 |
2 files changed, 259 insertions, 0 deletions
diff --git a/files/ja/conflicting/tools/performance/call_tree/index.html b/files/ja/conflicting/tools/performance/call_tree/index.html new file mode 100644 index 0000000000..858b944015 --- /dev/null +++ b/files/ja/conflicting/tools/performance/call_tree/index.html @@ -0,0 +1,114 @@ +--- +title: プロファイラのチュートリアル +slug: Tools/Performance/Profiler_walkthrough +translation_of: Tools/Performance/Call_Tree +translation_of_original: Tools/Performance/Profiler_walkthrough +--- +<div>{{ToolsSidebar}}</div><p>JavaScript プロファイラは JavaScript エンジンの状態を定期的にサンプリングして、その時点のコード実行のスタックを記録します。統計的に、個々の関数を実行しているときに取得したサンプル数はブラウザが実行にかけた時間に対応しますので、コード内のボトルネックを発見できます。</p> + +<h2 id="Analysing_profiles" name="Analysing_profiles">プロファイルを分析する</h2> + +<p>パフォーマンスツールがどのようにプロファイルを提供するかを理解するには、例を見ていくことがもっとも簡単です。以下のコードは 2 から 10,000 までの数値について素数であるかを確認して、その結果を表示します。少しおもしろくするため、素数の確認は <code><a href="/ja/docs/Web/API/WindowTimers.setTimeout">setTimeout</a></code> のコールバックとして実行します:</p> + +<pre class="brush: js">function isPrime(i) { + for (var c = 2; c <= Math.sqrt(i); ++c) { + if (i % c === 0) { + console.log(i + " is not prime"); + return; + } + } + console.log(i + " is prime"); +} + +function timedIsPrime(i) { + setTimeout(function() { + isPrime(i); + }, 100); +} + +function testPrimes() { + var n = 10000; + for (var i = 2; i != n; ++i) { + timedIsPrime(i); + } +} + +var testPrimesButton = document.getElementById("test-primes"); +testPrimesButton.addEventListener("click", testPrimes, false);</pre> + +<p>このコードを Web ページに貼り付けて実行すると、コンソールへ以下のように出力します:</p> + +<pre>"2 is prime" +"3 is prime" +"4 is not prime" +"5 is prime" +"6 is not prime"</pre> + +<p>このコードのプロファイルを取得すると、以下のように表示されるでしょう:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9511/primality-profile.png" style="display: block; margin-left: auto; margin-right: auto; width: 650px;"></p> + +<p>最初の行は、<em>関数</em>列が常に <em>(ルート)</em> になります。ここでは 2 つのことを示しています: プロファイリングに 1,121.95 ミリ秒かかっており、またその間に 78 個のサンプルを取得しました。<em>(ルート)</em> の下に、サンプルの取得中にプログラムで経由した、さまざまなパスのツリーを表示します。<em>(ルート)</em> の直下に、スタックの底にあるトップレベルの関数が現れます。この例では、トップレベルの関数が 2 つあります:</p> + +<ul> + <li>click イベントのリスナである <code>testPrimes()</code></li> + <li><code>timedIsPrime()</code> 内の <code>setTimeout()</code> の引数で指定した、無名のコールバック関数</li> +</ul> + +<p><code>testPrimes()</code> の行を見ていきましょう:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9515/primality-profile-testprimes.png" style="display: block; margin-left: auto; margin-right: auto; width: 650px;"></p> + +<p>ここでは、78 個のサンプルのうち 29 個を <code>testPrimes()</code> 内で取得したことがわかります。<em>合計コスト</em>の列は、サンプル数をパーセント値に置き換えたものです: <code>(29/78) * 100</code> =<code> 37.17</code></p> + +<p>ところが<em>時間</em>と<em>コスト</em>は、ともに 0 です。これは、そのスタックフレームのコードを実行している間に取得したサンプルがないためです。サンプルはすべて、関数内にネストしているブロックまたは <code>testPrimes()</code> が呼び出した関数の内部で取得したものです。これは次の行でわかります:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9517/primality-profile-testprimes-2.png" style="display: block; margin-left: auto; margin-right: auto; width: 650px;"></p> + +<p>この行も <em>testPrimes</em> という名称です。これは 19 行目から始まる <code>for</code> ループが作成した、<code>testPrimes()</code> の新たなスタックフレームを指しています。前のフレームの<em>コスト</em>が 0 であったことから予想されるとおり、このフレームの<em>サンプル</em>列も 29 です。</p> + +<p>しかし、<em>コスト</em>と<em>時間</em>は 0 ではありません。これはいくつかのサンプルが、このフレームを実行しているときに取得されたことを表します。プロファイルではサンプルをいくつ取得したかを明示していませんが、次の <em>timedIsPrime</em> という名前の行で取得したサンプルが 24 個であることから、5 個取得したはずです。これは簡単に確認できます。<code>(5/78) * 100 = 6.41</code> であり、<em>コスト</em>の値と一致します。</p> + +<p>この分岐で残る 24 個のサンプル (全体の 30.76%) は <code>timedIsPrime()</code> で取得されました。つまり、<code>setTimeout()</code> (12 行目) を呼び出している部分です。</p> + +<p>コールツリーの別の分岐は、<code>setTimeout()</code> (13 行目) に渡した無名のコールバック関数から始まっています。ここではサンプルを 1 個取得しており、残り 48 個のサンプル (全体の 61.53%) はコールバックで呼び出す <code>isPrime()</code> で取得されました。</p> + +<p>総括すると、もっとも多くのサンプルを <code>isPrime()</code> で取得しており (全体の 61.53%)、その次が <code>timedIsPrime()</code> (全体の 30.76%)、残りは取るに足らない量です。統計的に言えば、おそらくこれらの関数がほとんどの時間を消費していますので、プログラムを高速化したい場合の有力な最適化候補になります。</p> + +<h3 id="Total_Time_and_Self_Time" name="Total_Time_and_Self_Time"><em>合計時間</em>と<em>時間</em></h3> + +<p><em>合計時間</em>と<em>時間</em>の列は<em>合計コスト</em>と<em>コスト</em>から算出していますが、直接反映したものではありません。規則的にサンプルを取得しようとしていますが、そのとおりに取得できない場合もあります。適切な時期にサンプルを取得できなかった場合は、その不規則性を補正しようとします。</p> + +<h3 id="Inverting_the_call_tree" name="Inverting_the_call_tree">呼び出しツリーを反転</h3> + +<p>既定では、プロファイラは一般的なコールスタックと同様に、呼び出しツリーを根から葉の順に表示します。つまりそれぞれのトップレベル関数、トップレベル関数が呼び出す関数、その関数から呼び出される関数、といった順になります:</p> + +<pre>testPrimes + + -> timedIsPrime + + + +(setTimeout callback) + + -> isPrime</pre> + +<p>これは論理的かつスタックが積み上げられる時系列に従っており、コールスタックを表現するための慣習的な方法でもあります。一方、時間がかかっている場所が呼び出しツリーの深部にあることがよくあります。前出の例でわかるとおり、全サンプルの 90% は 2 つの主要な分岐の終端で発生しています。</p> + +<p>多くのサンプルを記録したスタックフレームに注目させるため、呼び出しツリーを反転させるオプションがプロファイラにあります。このオプションを選択すると、プロファイラは以下のようになります:</p> + +<ul> + <li><em>コスト</em>が 0 より大きいスタックフレーム、つまり、サンプルを取得したとき実際に実行していたスタックフレームのリストを作成します。</li> + <li>リストは、スタックフレームで取得したサンプル数の順に並べ替えられます。</li> + <li>リスト内の各項目で、コールスタックをトップレベル関数に向かって逆向きに表示します。</li> +</ul> + +<p>例えば testPrimes の例を、既定の表示でもう一度示します:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9511/primality-profile.png" style="display: block; margin-left: auto; margin-right: auto; width: 650px;"></p> + +<p>呼び出しツリーを反転すると以下のようになります:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9521/primality-profile-inverted.png" style="display: block; margin-left: auto; margin-right: auto; width: 650px;"></p> + +<p>反転した表示では、プログラムで時間がかかっている場所を効果的に目立たせていることがわかるでしょう。</p> diff --git a/files/ja/conflicting/tools/performance/index.html b/files/ja/conflicting/tools/performance/index.html new file mode 100644 index 0000000000..c05f177c25 --- /dev/null +++ b/files/ja/conflicting/tools/performance/index.html @@ -0,0 +1,145 @@ +--- +title: JavaScript プロファイラ +slug: Tools/Profiler +tags: + - Debugging + - Firefox + - Guide + - Profiler + - Profiling + - Tools +translation_of: Tools/Performance +translation_of_original: Tools/Profiler +--- +<div>{{ToolsSidebar}}</div><p>プロファイラツールを使用して、JavaScript コードのボトルネックを見つけましょう。プロファイラは周期的に、サンプルについて現在の JavaScript コールスタックやコンパイルの統計情報を抽出します。</p> + +<p>"Web 開発" メニューから "プロファイラ" を選択することで、プロファイラを起動できます。"Web 開発" メニューは、Linux や OS X では "ツール" メニューの配下に、Windows では "Firefox" メニューの直下にあります。</p> + +<p><a href="/ja/docs/Tools/Tools_Toolbox" title="Tools/Tools_Toolbox">ツールボックス</a>が開いて、プロファイラが選択されます。</p> + +<h2 id="Sampling_profilers" name="Sampling_profilers"><a name="sampling-profilers">サンプリング型プロファイラ</a></h2> + +<p>JavaScript プロファイラは、サンプリング型のプロファイラです。これは JavaScript エンジンの状態を定期的にサンプリングして、その時点のコード実行のスタックを記録します。統計的に、個々の関数を実行しているときに取得したサンプル数はブラウザが実行にかけた時間に対応しますので、コード内のボトルネックを発見できます。<br> + <br> + <a name="profiling-example">例えば、以下のようなプログラムについて考えてみましょう:</a></p> + +<pre class="brush: js">function doSomething() { + var x = getTheValue(); + x = x + 1; // -> サンプル A + logTheValue(x); +} + +function getTheValue() { + return 5; +} + +function logTheValue(x) { + console.log(x); // -> サンプル B、サンプル C +} + +doSomething();</pre> + +<p>プロファイラをアクティブにしてこのプログラムを実行したら、実行時にプロファイラは上記のインラインコメントで示したように 3 つのサンプルを取得します。</p> + +<p>これらはすべて <code>doSomething()</code> の内部から取得されますが、2 番目の 2 つは <code>doSomething()</code> から呼び出された <code>logTheValue()</code> 関数の内部です。よってプロファイルは、以下のように 3 つのスタックトレースで構成されます:</p> + +<pre>サンプル A: doSomething() +サンプル B: doSomething() > logTheValue() +サンプル C: doSomething() > logTheValue()</pre> + +<p>これは私たちに何も伝えられない不十分なデータであることが明らかですが、より多くのサンプルにより、<code>logTheValue()</code> がコード内のボトルネックであると断定できるかもしれません。</p> + +<h2 id="Creating_a_profile" name="Creating_a_profile">プロファイルの作成</h2> + +<p>プロファイラで<em>ストップウォッチ</em>のボタンをクリックして、サンプルの記録を始めます。プロファイラが記録を行っている間は、ストップウォッチのボタンがハイライトされます。ボタンを再度押すと記録を停止して、新たなプロファイルを保存します:</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>"終了" をクリックすると、新しいプロファイルが自動的に開きます:</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>このペインは 2 つのパーツに分かれています:</p> + +<ul> + <li>左側は取得したすべてのプロファイルを一覧表示しており、それぞれのプロファイルを読み込むことができます。また、リストの上にボタンが 2 つあります。<em>ストップウォッチ</em>のボタンは新たなプロファイルの記録を、<em>インポート...</em> ボタンは以前に保存したデータのインポートを行います。プロファイルを選択しているときは、<em>保存</em>ボタンをクリックするとデータを JSON ファイルとして保存できます。</li> + <li>右側は現在読み込んでいるプロファイルを表示します。</li> +</ul> + +<h2 id="Analyzing_a_profile" name="Analyzing_a_profile">プロファイルの分析</h2> + +<p>プロファイルは 2 つのパーツに分かれています:</p> + +<ul> + <li><a href="#profile-timeline" title="#profile-timeline">プロファイルのタイムライン</a></li> + <li><a href="#profile-details" title="#profile-details">プロファイルの詳細</a></li> +</ul> + +<h3 id="Profile_timeline" name="Profile_timeline"><a 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>チャートで赤色のサンプルは、そのときにブラウザが応答していなかったことを示しており、ユーザはアニメーションや応答性が止まったことに気づいたかもしれません。プロファイルに赤色のサンプルがある場合は、そのコードをいくつかのイベントに分解することを検討したり、<a href="/ja/docs/Web/API/window.requestAnimationFrame" title="Web/API/window.requestAnimationFrame">requestAnimationFrame</a> や <a href="/ja/docs/Web/Guide/Performance/Using_web_workers" title="Web/Guide/Performance/Using_web_workers">Worker</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>タイムラインの上に "サンプリング範囲 [AAA, BBB]" というラベルがついた、新たなボタンが現れます。そのボタンを押すとプロファイルがズームされて、そのタイムスライスの詳細なビューが下部に表示されます:</p> + +<p><br> + <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="Profile_details" name="Profile_details"><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;">始めに新しいサンプルを開くと、サンプルペインには上のスクリーンショットのように "(total)" という名前の行があります。"(total)" の隣にある三角印をクリックすると、サンプル内にあるすべてのトップレベル関数がリストアップされます。</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/5995/Screen%20Shot%202013-08-26%20at%2011.22.10%20AM.png"></p> + +<p><strong>実行時間</strong>は当該関数が現れたサンプルの総数を示し<a href="#footnote-1"><sup>1</sup></a>、その後ろにプロファイル内で当該関数が現れた全サンプルのパーセント値があります。最上段の行はプロファイル全体で 2021 のサンプルがあることを表し、また 2 行目は 1914 サンプルすなわち全体の 94.7% が、<code>detectImage()</code> 関数内にいたことを表します。</p> + +<p><strong>滞在</strong> は当該関数そのものを実行する間に取得したサンプル数を示しており、関数を呼び出しているときではありません。前出の<a href="#profiling-example" title="#profiling-example">シンプルな例</a>では、<code>doSomething()</code> は<strong>実行時間</strong>が 3 (サンプル A、B、C) ですが、<strong>滞在</strong>の値は 1 (サンプル A) になるでしょう。</p> + +<p>3 列目は関数名およびファイル名と行数 (ローカルの関数) またはベースネームとドメイン名を表示します。灰色の関数はブラウザ組み込みの関数です。黒色の関数がページで読み込んだ JavaScript を表します。行にマウスポインタを乗せると、関数の識別名の右側に矢印が現れます: 矢印をクリックすると関数のソースを表示します。</p> + +<h3 id="Expanding_the_call_tree" name="Expanding_the_call_tree">コールツリーの展開</h3> + +<p>ある行で、この関数から呼び出された関数に滞在している間のサンプルが存在する場合 (すなわち、<strong>実行時間</strong>がその行の<strong>滞在</strong>より大きい場合) は、関数名の左側に三角印が表示され、コールツリーを展開できます。</p> + +<p>前出の<a href="#profiling-example" title="#profiling-example">シンプルな例</a>では、完全に展開したコールツリーは以下のようになります:</p> + +<table class="standard-table" style="height: 100px; width: 378px;"> + <tbody> + <tr> + <td style="text-align: center;"><strong>実行時間</strong></td> + <td style="text-align: center;"><strong>滞在</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>より実際的な例を見ましょう: 前出のスクリーンショットで、上から 2 行目を見ると <code>detectImage()</code> 関数の内部で 1914 サンプルかかっていることがわかります。しかし、そのすべては <code>detectImage()</code> から呼び出された関数でかかっています (<strong>滞在</strong> セルが 0 です)。コールツリーを展開して、ほとんどのサンプルがかかっていたとき実際に実行していた関数は何かを明らかにできます:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/5999/bla.png" style="display: block; margin-left: auto; margin-right: auto;"></p> + +<p>これは、<code>detectAtScale()</code> を実際に実行しているときに 6 サンプル、<code>getRect()</code> の実行に 12 サンプルかかっていたことなどを表します。</p> + +<h2 id="Footnotes" name="Footnotes">脚注</h2> + +<ol> + <li><a name="footnote-1">関数がさまざまなソースから複数回呼び出される場合、プロファイラの出力にも複数回現れます。よって、<code>forEach</code> など汎用的な関数はコールツリー内に複数回現れるでしょう。</a></li> +</ol> |