Firefox 48 より前のバージョンでは、このビューがヒープスナップショットの既定のビューでした。Firefox 48 より既定のビューが ツリーマップビュー になりましたが、"表示:" のドロップダウンリストで総計ビューに切り替えできます:
総計ビューは、以下のようなものです:
これは、ヒープの内容の内訳を表形式で表示します。データをグループ化する方法は、主に 3 つあります:
これらは、パネルの上部にある "グループ化" ドロップダウンリストで変更できます:
また、ペインの右上に "フィルター" と表示されているボックスがあります。表示するスナップショットの内容をフィルタリングできますので、例えば特定のクラスのオブジェクトがいくつアロケートされているかをすばやく確認できます。
Type
これはデフォルトのビューであり、以下のようなものです:
このビューは、ヒープの内容を以下のタイプに分類します:
- JavaScript オブジェクト:
Function
やArray
など。 - DOM 要素:
HTMLSpanElement
やWindow
など。 - 文字列:
"strings"
として表示。 - JavaScript ソース: "
JSScript"
として表示。 - 内部オブジェクト: "
js::Shape
" など。これらは接頭辞"js::"
がつきます。
それぞれのタイプを表の行に表示して、これらの行は、そのタイプのオブジェクトが占めるメモリーの量の順に並べます。例えば前出のスクリーンショットでは、JavaScript の Object
がもっとも多くのメモリ、また strings が 2 番目に多くのメモリーを占めていることがわかります。
- "合計数" 列では、現時点で割り当てられているオブジェクトの数をカテゴリー別に表示します。
- "合計バイト" 列でそれぞれのカテゴリーのオブジェクトが占めるメモリーのバイト数と、タブの合計ヒープサイズに対する割合を表示します。
例えば前出のスクリーンショットでは、以下のことがわかります:
Array
オブジェクトが 4 個ある。- それらはヒープ全体の 15% を占める。
タイプ名の隣に、3 つの星印が三角形のように配置されているアイコンがあります:
これをクリックすると、そのタイプのすべてのインスタンスを確認できます。例えば Array
では、スナップショット内に Array
オブジェクトが 4 個あると表示しています。3 つの星印をクリックすると、4 個の Array
インスタンスを表示します:
それぞれのインスタンスで、保持サイズとシャローサイズ を確認できます。このスクリーンショットでは、上から 3 個の配列のシャローサイズがかなり多く (ヒープ全体の 5%)、またより多くの保持サイズ (全体の 26%) を占めていることがわかります。
右側には、"保持パスを表示するノードを選択してください" と表示されているペインがあります。項目を選択すると、その項目の 保持パスパネル を表示します:
Call Stack
Call Stack では、コードのどこでメモリーの割り当てを行っているかを表示します。
メモリー割り当てのトレースは負荷が高いため、スナップショットでメモリー割り当てが行われる前に "割り当てスタックを記録" にチェックを入れて、明示的に有効化しなければなりません:
オブジェクトの割り当てを行ったすべての関数を、割り当てたサイズ順に並べて表示します:
このビューの構造は コールツリー の構造とよく似ていますが、プロセッサーのサンプルではなく割り当てのみ表示します。例えば、最初の項目では以下のことがわかります:
- ヒープ全体の 93% を占める 4,832,592 バイトを、"alloc.js" の 35 行目にある関数またはその関数が呼び出した関数が割り当てました。
展開用の三角印を使用してコールツリーの細分化が可能であり、コード内で割り当てを行った箇所を正確に知ることができます。
シンプルな例を使用して、簡単に説明します。ここでは DOM allocation example を使用します。このページは大量の DOM ノード (200 個の HTMLDivElement
オブジェクトと 4000 個の HTMLSpanElement
オブジェクト) を生成するスクリプトを実行します。
メモリ割り当てをトレースしてみましょう:
- メモリツールを開きます。
- "割り当てスタックを記録" にチェックを入れます。
- https://mdn.github.io/performance-scenarios/dom-allocs/alloc.html を開きます。
- スナップショットを採取します。
- "表示/総計" を選択します。
- "グループ化/Call Stack" を選択します。
ビューは以下のようになるでしょう:
これは、ヒープスナップショット全体の 93% を "alloc.js" の 35 行目で呼び出した関数 (始めに呼び出す createToolbars()
) が割り当てていることを示しています。
展開用の三角印を使用してツリーを展開すると、どこでメモリーの割り当てを行っているかを正確に知ることができます:
ここでは "バイト" 列と "個数" 列が役に立ちます。これは割り当てたメモリーのサイズと、割り当て数を示します。
前出の例では alloc.js の 9 行目・23 桁目 にある createToolbarButton()
で 4002 個のメモリー領域を割り当てており、それはヒープ全体の 84% を占めています。つまり正確な場所は、<span>
要素を生成している場所です。
ファイル名と行番号はリンクになっています。クリックすると、デバッガーでその行を表示します:
Inverted Call Stack
Call Stack ビューは、トップダウン型です。これは、メモリーの割り当てが発生した箇所をコールツリーの深部に表示します。よって、プログラムのどこでメモリーを大量に消費しているかの概要を知るのに適しています。しかし、このビューでは割り当てが発生した正確な場所を知るために、ツリーを長くたどらなければなりません。
"Inverted Call Stack" ビューが役に立ちます。これはメモリー割り当てが発生した正確な場所を、割り当てサイズの順に並べたボトムアップ型のビューです。ツリーを展開すると、トップレベルに向かってコールツリーをたどります。
上記の例で "Inverted Call Stack" を選択すると、どのようになるかを見てみましょう:
リストの最初に、ページでヒープの 89% を占めている createToolbarButton()
があります。
(有効なスタックはありません)
前出の例で、ヒープの 7% が "(有効なスタックはありません)" であることに気づいているでしょう。これは、ヒープのすべてを JavaScript で使用しているわけではないためです。
例えば、以下のようなものがあります:
- ページで読み込んだスクリプトが、ヒープ領域を使用しています。
- JavaScript がスタックに存在しないときに、オブジェクトが割り当てられる場合があります。例えば DOM の
Event
は、JavaScript を実行してイベントハンドラーを呼び出す前に割り当てられます。
実在するページの多くは、"(有効なスタックはありません)" の割合が 7% を超えます。