V8 CPU とメモリのプロファイリング
JetBrains Rider で、 V8 のサンプルベースプロファイラーを使って Node.js アプリケーションの CPU プロファイルやヒープスナップショットをキャプチャし、分析できます。
Google Chrome DevTools でキャプチャされたスナップショットを開いて、クライアント側コードの調査もできます。
始める前に
CPU プロファイリング
CPU プロファイリングを使うと、コードのどの部分が最も CPU 時間を消費しているか、また V8 JavaScript エンジンによるコードの実行や最適化の仕組みをより理解できます。
JetBrains Rider の Node.js CPU プロファイリングは、V8 組み込み CPU プロファイラーに基づいています。これは、コードの実行と JavaScript エンジン自体の動作(ガベージコレクションサイクル、コンパイル・再コンパイル、コード最適化など)についての情報を提供します。
プロファイラは、ティックと呼ばれる一定の間隔でスナップショットを撮ります。 測定は、コードの作業だけでなく、コンパイル、システムライブラリの呼び出し、最適化、ガベージコレクションなど、エンジン自体によって実行されるアクティビティについても行われます。
CPU プロファイリングを有効にする
アプリケーションの起動時に V8 CPU プロファイリングを呼び出すには、 Node.js 実行構成で追加設定を指定する必要があります。
に進みます。 または、ツールバーの 実行 ウィジェットから 実行構成の編集 を選択します。

開いた 実行構成の編集 ダイアログで、ツールバーの 追加 ボタン (
) をクリックし、リストから Node.js を選択します。
リストから Node.js 実行構成を選択して CPU プロファイリングを有効にするか、 Node.js の実行とデバッグ の説明に従って新しい設定を作成します。
V8 プロファイリング タブに切り替えて、 CPU プロファイリング情報を記録する チェックボックスを選択します。 ログフォルダー フィールドに、記録されたログが保存されるフォルダーへのパスを指定します。ログファイルは
isolate-<session number>という名前で保存されます。
CPU プロファイリング情報を収集する
メインツールバーのリストから実行構成を選択して
をクリックするか、メインメニューから を選択します。
プロファイルする必要があるシナリオが実行されたら、ツールバーの
をクリックしてプロセスを停止します。
CPU プロファイリングログの分析
アプリケーションを停止すると、JetBrains Rider は自動的に V8 プロファイリング ツールウィンドウを開き、収集したプロファイリングデータを表示します。 ウィンドウが既に開いていて別のセッションの収集データを表示している場合は、JetBrains Rider は新しいタブを開きます。 自動的に開かれたタブには、アプリケーションの実行を制御し、プロファイリングデータを収集する実行構成に基づいて名前が付けられます。
以前に保存したプロファイリングデータを開いて分析するには、 に移動して(または Ctrl+Shift+A を押して)、 V8 と入力し始め、リストから V8 プロファイリングログの解析 を選択します。

次に、関連する V8 ログファイル isolate-<session number> を選択します。 JetBrains Rider は、選択したログファイルの名前で個別のタブを作成します。
収集されたプロファイリングデータに基づいて、JetBrains Rider は呼び出しツリーを 3 つ構築し、それぞれを別々のペインに表示します。 これらの呼び出しツリーを使って、アプリケーションの実行を 2 つの異なる観点から分析可能です。一方は時間がかかった(「重い」)呼び出し、もう一方は「誰が誰を呼び出したか」です。
呼び出しツリーのメトリクスを理解する
呼び出しツリーは、関数内のティック数またはその合計実行時間に対する比率を表す 合計および セルフメトリクスを使用します。
Total は、関数内で費やされた時間とそれが呼び出した関数を示します。
Self は、子ノードを考慮せずに、関数自体の内部でのみ費やされた時間を示します。
親メトリクスは、それを呼び出した関数の実行時間に対する関数の純粋な実行時間の比(親 )を示します。
V8 オプティマイザー
場合によっては、V8 でコードを最適化できます。 詳細については、 V8 の最適化(英語)を参照してください。
機能名の前のアスタリスク
*は、その機能が最適化されたことを示します。チルダ
~は、関数が最適化を必要としている可能性があるが、最適化されていないことを示します。 コードが短期間の場合、エンジンは最適化を延期するかスキップする場合がありますが、パフォーマンスを向上させるためにコードを書き直すことができる場所をチルダで示します。
トップ呼び出しツリー
トップ呼び出し ペインには、実行されたアクティビティが セルフメトリクスでソートされた降順で一覧表示されます。 各活動について、その 合計、 合計 %、 自己 % メトリクスが表示されます。 各関数呼び出しについて、JetBrains Rider は関数が定義されているファイル名、行、列を表示します。

概要 ペインのダイアグラムは、 自己 % メトリクスが 1% を超えるコールの セルフ時間の分布を示しています。
ボトムアップツリー
ボトムアップ ペインには、 セルフメトリクスによって降順にソートされた実行済みアクティビティも一覧表示されます。 トップ呼び出し ペインとは異なり、 ボトムアップ ペインには、 合計 % メトリクスが 2 を超えるアクティビティと呼び出した関数のみが表示されます。
アクティビティごとに、 ティックでの実行時間と 親メトリクスが表示されます。
各関数呼び出しについて、JetBrains Rider は関数が定義されているファイル名、行、列を表示します。

トップダウンツリー
トップダウン ペインには、呼び出し階層全体が表示され、上部には実行エントリポイントである関数が表示されます。 各活動について、その 合計、 合計 %、 セルフ、 自己 % メトリクスが表示されます。 各関数呼び出しについて、JetBrains Rider は関数が定義されているファイル名、行、列を表示します。

呼び出しツリーを移動する
機能のソースコードに移動するには、この機能を選択してツールバーの F4 または
を押すか、コンテキストメニューから ソースに移動 を選択します。
別のペインに切り替えて別の観点から呼び出しを調べるには、呼び出しを選択し、呼び出しのコンテキストメニューから 次に移動する を選択してから、宛先を選択します。 JetBrains Rider は選択したペインに切り替え、フォーカスをその呼び出しに移動します。
ノードを展開または折りたたむ
JetBrains Rider がプロファイリングセッション用のタブを開くと、デフォルトで最も負荷の高い呼び出しがあるノードを展開します。 ツリーを探索しているときに、これらのノードの一部を折りたたんだり、他のノードを展開したりすることもできます。
ノードを展開または折りたたむには、そのコンテキストメニューから ノードの展開 または ノードを折りたたむ を選択します。
アクティブペイン内のすべてのノードを折りたたむには、ツールバーの
をクリックします。
元のツリー表示に戻すには、
をクリックします。
軽量な呼び出しをフィルタリングする
パフォーマンス上の問題を実際に引き起こしている呼び出しだけを確認するには、これを実行してください。
ツールバーの
をクリックしてから、スライダを使用して、表示される呼び出しの 合計 % または 親 % の最小値を指定し、 終了 をクリックします。
プロファイリングデータを保存して比較する
関数とそのメトリクスを含む行を保存するには、その関数のコンテキストメニューから Copy を選択します。 これは、たとえばコードを改善した後など、2 つのセッションからの関数の測定値を比較したい場合に役立ちます。
関数名とそれが定義されているファイルの名前だけを保存するには、関数のコンテキストメニューから 呼び出しのコピー を選択します。
アイテムをクリップボードの内容と比較するには、アイテムのコンテキストメニューから クリップボードと比較 を選択します。 JetBrains Rider は 差分ビューアーを開きます。
現在のログを他のログと比較するには、ツールバーの
をクリックします。 開いたダイアログで、現在のものと比較するためにアイソレートを選択します。 検索対象を絞り込むには、ターゲット分離株が現在の分離株の前後どちらにあるかを指定します。
呼び出しツリーをエクスポートする
現在のペインの呼び出しツリーをテキストファイルに保存するには、ツールバーの
をクリックして、表示されるダイアログでターゲットファイルを指定します。
フレームチャートの分析
多色 フレームチャート を使用して、アプリケーションがどこで一時停止したかを見つけ、これらの一時停止を引き起こした呼び出しを調べます。

チャートは 4 つの領域で構成されています:
上部の領域には、調査するフラグメントの先頭と最後を制限する 2 つのスライダを持つタイムラインが表示されます。
下の領域には、多色のチャートの形で呼び出しのスタックが表示されます。 最初に呼び出されると、各関数にはランダムな色が割り当てられ、現在のセッション内のこの関数のすべての呼び出しがこの色で表示されます。
中央の領域には、 ガベージコレクタからの呼び出し、エンジン、外部呼び出し、実行自体の概要が表示されます。 これらの活動のために予約されている色はエリアの上にリストされています。
右側のペインには、選択した断片内の呼び出しが一覧表示されます。各呼び出しについて、リストにはその所要時間、呼び出された関数の名前、および関数が定義されているファイルが表示されます。
下部と右側の領域は同期しています。下部領域のスライダーをタイムライン上でドラッグすると、右側のペインのフォーカスがそのとき実行されていたコールに移動します。
さらに、下部の領域でコールをクリックすると、スライダーが自動的にそのコールに移動し、右側のペインのフォーカスが対応する機能に切り替わり、必要に応じてリストが自動的にスクロールします。 逆に、リストの項目をクリックすると、JetBrains Rider は下部エリアで対応する呼び出しを選択し、スライダーを自動でそこまで移動します:
タイムラインでフラグメントを選択する
特定の期間内のプロセスを調べるには、タイムラインで対応するフラグメントを選択する必要があります。 これを行うには、スライダーをドラッグするか、2 つのスライダー間の ウィンドウをクリックして、必要なフラグメントまでドラッグします。
いずれの場合も、下の多色チャートには選択されたフラグメント内のコールスタックが表示されます。
チャートを拡大するには、選択したフラグメントをクリックし、ツールバーの
をクリックします。 JetBrains Rider は新しいタブを開き、選択したフラグメントをタブ幅いっぱいに拡大表示するため、より詳細に確認できます。
フレームチャートを移動する
右側の領域の呼び出しから、呼び出された関数のソースコード、ツールウィンドウの他のペイン、また特定のメトリクスを持つフレームチャート内の領域にジャンプできます。
呼び出された関数のソースコードに移動するには、呼び出しのコンテキストメニューから ソースに移動 を選択してください。
呼び出しの特定のメトリクスを持つフラグメントでフレームチャートを拡大するには、呼び出しを選択し、呼び出しのコンテキストメニューから 次に移動する を選択してから、メトリクスを選択します。
呼び出しのスタックトレースに移動して、例外を表示および分析することもできます。 それには、呼び出しのコンテキストメニューから スタックトレースとして表示 を選択します。 JetBrains Rider は別のタブでスタックトレースを開き、 フレームチャート ペインへ戻るには下部の V8 CPU プロファイリング ツールウィンドウボタンをクリックしてください。
メモリプロファイリング
メモリプロファイリングを使うと、メモリリークや動的メモリの問題を検出し、それらを引き起こしたコードの断片を特定できます。
メモリプロファイリングを有効にする
アプリケーション起動時にメモリスナップショットの取得を起動するには、 Node.js 実行構成で追加設定を指定する必要があります。
に進みます。 または、ツールバーの 実行 ウィジェットから 実行構成の編集 を選択します。

開いた 実行構成の編集 ダイアログで、ツールバーの 追加 ボタン (
) をクリックし、リストから Node.js を選択します。
リストから、 Node.js の実行構成を選択して CPU プロファイリングをアクティブにするか、 Node.js 実行 / デバッグ構成を作成する に従って新しいコンフィギュレーションを作成します。
V8 プロファイリング タブに切り替えて、 ヒープスナップショットの取得を許可する チェックボックスを選択します。
メモリプロファイリング情報を収集する
メインツールバーのリストから実行構成を選択して
をクリックするか、メインメニューから を選択します。
アプリケーションの実行中はいつでも、 実行 ツールウィンドウのツールバーの
をクリックします。
表示されるダイアログで、スナップショットの名前と保存先フォルダーへのパスを指定します。 スナップショットの分析をすぐに開始するには、 スナップショットを開く チェックボックスを選択します。
メモリスナップショットの分析
スナップショットを取得し分析を選択すると、JetBrains Rider は収集したデータを含む V8 ヒープ ツールウィンドウを開きます。 ウィンドウが既に開いていて別のセッションの収集データを表示している場合は、JetBrains Rider は新しいタブを開きます。
以前に保存したメモリプロファイリングデータを開いて分析するには、 に移動します(または Ctrl+Shift+A を押して、 V8 の入力を開始し、リストから V8 ヒープスナップショットの解析 を選択します。

次に、関連する .heapsnapshot ファイルを選択します。 JetBrains Rider は、選択したファイルの名前で個別のタブを作成します。
ツールウィンドウには、さまざまな観点から収集された情報を表示するタブが 3 つあります。
包含 タブでは、アプリケーション内のオブジェクトが複数のトップレベル項目、すなわち DOMWindow オブジェクト、 ネイティブブラウザーオブジェクト、 GC ルート の下にグループ化されて表示されます。これらは ガベージコレクター が実際に使用するルートです。 詳細については、 Containment View を参照してください。
各オブジェクトについて、このタブでは GC ルートからの距離 、つまりそのオブジェクトと GC ルートの間のノードの最短単純パス、さらにオブジェクトの シャローサイズと 保持サイズを表示します。 オブジェクトのサイズの絶対値に加えて、JetBrains Rider はそのオブジェクトが占めているメモリの割合も表示します。
最大オブジェクト タブには、 保持サイズでソートされた、最もメモリを消費するオブジェクトが表示されます。 このタブでは、グローバルオブジェクトにデータを蓄積することによって引き起こされるメモリリークを見つけることができます。
要約 タブには、アプリケーション内のオブジェクトがタイプ別にグループ化されて表示されます。 タブには、各タイプのオブジェクトの数、サイズ、占有しているメモリの割合が表示されます。 この情報は、メモリ状態の手掛かりになる場合があります。
各タブには 詳細 ペインがあり、GC ルートから現在選択されているオブジェクトへのパスとオブジェクトの リテイナのリスト、つまり選択されたオブジェクトへのリンクを保持するオブジェクトが表示されます。 すべてのヒープスナップショットには多くの「バック」参照とループがあるため、オブジェクトごとに多数のリテイナーが常に存在します。
オブジェクトにテキストラベルを付ける
ラベルを使うことで、オブジェクトを区別したり、コンテキストを失うことなく別のオブジェクトへ移動したりできます。
オブジェクトにラベルを設定するには、オブジェクトを選択してツールバーの
をクリックするか、コンテキストメニューから マーク を選択します。 次に開いたダイアログでテキストラベルを指定します。
スナップショットを移動する
オブジェクトに対応する関数または変数に移動するには、このオブジェクトを選択してツールバーの
をクリックするか、コンテキストメニューから ソースの編集 を選択します。 ボタンやメニューオプションが無効な場合、JetBrains Rider は選択されたオブジェクトに対応する関数や変数を見つけられなかったことを意味します。
複数の関数や変数が見つかった場合、JetBrains Rider はそれらを候補リストに表示します。
封じ込めの観点からオブジェクトを調査しオブジェクト間のリンクに注目できるように、JetBrains Rider では 最大オブジェクト または 要約 タブ、 出現箇所 ビュー上のオブジェクトから 包含 タブの同じオブジェクトにジャンプできます。
これを行うには、オブジェクトを選択し、コンテキストメニューから メインツリー内の移動 を選択します。
スナップショットを検索する
包含 タブで、ツールバーの
をクリックします。
表示される V8 ヒープ検索 ダイアログで、検索パターンと検索範囲を指定します。 使用可能な範囲は次のとおりです。
すべての場所で すべてのスコープを検索するには、このチェックボックスを選択してください。 このチェックボックスを選択すると、他の検索タイプはすべて無効になります。
リンク名: C++ ランタイムを呼び出すときに V8 が作成するオブジェクト名の中から検索するには、このチェックボックスを選択します。
V8 ヒープ ツールウィンドウでは、リンク名は
%文字%<link name>でマークされています。クラス名:: このチェックボックスを選択すると、関数コンストラクターを検索できます。
テキスト文字列: このチェックボックスを選択すると、オブジェクトの内容でテキスト検索が実行されます。
スナップショットのオブジェクト ID: このチェックボックスを選択すると、オブジェクトの一意の識別子を検索できます。 V8 は、オブジェクトが作成されるときにその形式でそのような固有の ID を各オブジェクトに割り当て、オブジェクトが破棄されるまでそれを保存します。 つまり、同じセッション内で作成された複数のスナップショットで同じオブジェクトを見つけて比較することができます。
V8 ヒープ ツールウィンドウでは、オブジェクト ID は
@文字@<object id>でマークされています。マーク: このチェックボックスを選択して、 包含 タブのツールバーの
をクリックして、オブジェクトに手動で設定したラベルを検索します。
検索結果は、 詳細 ペインに別の '<search pattern>' の出現 ビューで表示されます。 指定した検索範囲で検索結果をグループ化して表示するには、ツールバーの タイプ別にグループ化 トグルボタンを押します。
次回ダイアログを開いたとき、前回の検索時の設定が表示されます。