メモリ使用量データの分析 (JavaScript)
このトピックでは、JavaScript メモリ アナライザーについて説明します。このツールは、Visual Studio 2012 更新プログラム 1 で JavaScript を使用して開発された Windows ストア アプリに対して使用できます。ツールの使い方に関するチュートリアルについては、「チュートリアル: メモリ リークの検出 (JavaScript)」を参照してください。
メモリ使用量データの表示
JavaScript メモリ アナライザーは、作業用の Windows ストア アプリが Visual Studio で開かれているときに使用できます。
JavaScript メモリ アナライザーを実行するには
アプリを Visual Studio から実行している場合は、[デバッグ] ツール バーの [デバッグの開始] ボックスの一覧から、[ローカル コンピューター]、[シミュレーター]、または [リモート コンピューター] をクリックします。
これらのオプションの詳細については、「Visual Studio からの Windows ストア アプリの実行」を参照してください。
[デバッグ] メニューの [JavaScript メモリ分析] をポイントし、次のいずれかをクリックします。
[Launch Startup Project] (スタートアップ プロジェクトを起動): 現在のスタートアップ プロジェクトを開始するには、このオプションをクリックします。リモート コンピューターでアプリを実行している場合はこのオプションをクリックする必要があります。
[インストール済みのアプリ パッケージの起動]: インストールされているアプリを分析用に選択するには、このオプションをクリックします。このオプションは、リモート コンピューター上でアプリを実行しているときはサポートされません。
このオプションを使用すると、ソース コードにアクセスできないときに、コンピューターにインストールされているアプリのメモリ使用量を分析できます。このオプションは、自分が開発に携わっていないアプリのメモリ使用量を分析する場合にも便利です。
[実行中のアプリにアタッチ]: 実行中のアプリの一覧からアプリを選択するには、このオプションをクリックします。このオプションは、リモート コンピューター上でアプリを実行しているときはサポートされません。
このオプションを使用すると、ソース コードにアクセスできないときに、コンピューター上で実行されているアプリのメモリ使用量を分析できます。
メモリ アナライザーを起動したとき、VsEtwCollector.exe を実行するアクセス許可を要求するユーザー アカウント制御が表示される場合があります。[はい] をクリックします。
Alt キーを押しながら Tab キーを押して Visual Studio に切り替えます。
JavaScript メモリ アナライザーの[概要] ビューが [診断ハブ] タブに表示されます。
メモリ使用量ビュー
JavaScript メモリ アナライザーを実行すると、メモリ使用量データに関して以下のビューを使用できます。
[概要] ビュー.実行中のアプリおよびすべてのスナップショット概要タイルのコレクションのメモリ使用量グラフを示します。このビューは、[診断ハブ] タブに表示されます。
スナップショットの詳細の表示.単一のスナップショットの詳細なメモリ使用量データを示します。
スナップショットの相違の表示.詳細なメモリ使用量データを 2 つの選択したスナップショット間の相違値として示します。
[概要] ビュー
概要ビューは、実行中のアプリおよびすべてのスナップショット概要タイルのコレクションのメモリ使用量グラフを示します。このビューでは、スナップショットの取得、概要情報の分析、他のビューへの移動など、基本的なタスクを実行できます。
メモリ グラフには、プライベート バイト、ネイティブ メモリ、および JavaScript ヒープを含むアプリのプロセスのメモリのライブ ビューが示されます。グラフの例を次に示します。
メモリ グラフは、プロセス メモリのスクロール可能なビューです。
アプリ コードにプロファイル マークが追加されている場合、コードの該当セクションにいつ到達したかを示すユーザー マークの三角形がメモリ使用量グラフに表示されます。詳細については、「JavaScript コンソール コマンド」を参照してください。
メモリ グラフに示されるメモリの一部は、JavaScript ランタイムによって割り当てられます。アプリでこのメモリの使用を制御することはできません。グラフに表示されるメモリ使用量は、最初のスナップショットを取得したときに増加し、その後は追加のスナップショットを取得するたびに最小限増加します。
スナップショットの概要の表示
概要ビューの [ヒープ スナップショットの作成] をクリックすると、アプリのメモリ使用量に関する現在の状態のスナップショットを取得できます。また、同様に概要ビューに表示されるスナップショットの概要タイルには、JavaScript ヒープに関する情報と、詳細情報へのリンクが示されます。複数のスナップショットを取得している場合、前のスナップショットのデータと比較した追加情報が提供されます。
注意
JavaScript メモリ アナライザーは、スナップショットを取得する前にガベージ コレクションを強制的に実行します。これにより、実行間における結果の一貫性が保証されます。
この図は、前のスナップショットが取得されたときのスナップショットの例を示しています。
スナップショットの概要には、次の情報が表示されます。
スナップショットのタイトルとタイムスタンプ。
ヒープ サイズ (左側の青のテキスト)。この数値には、JavaScript ランタイム エンジンによって JavaScript ヒープに追加された DOM 要素およびオブジェクトが含まれます。ヒープ サイズは、スナップショットのドミネーター ビューにリンクしています。
ヒープ サイズの相違 (左側の赤または緑のテキスト)。この値は、現在のスナップショットのヒープ サイズと前のスナップショットのヒープ サイズとの相違を示しています。メモリが増加している場合は値が赤で表示され、それ以外の場合は緑で表示されます。ヒープのサイズが同じ場合、値は [相違なし] となります。最初のスナップショットの値は、単に [ベースライン] (灰色のテキスト) です。この値は、スナップショットの相違のドミネーター ビューにリンクしています。
オブジェクトの数 (右側の青のテキスト)。この値は、アプリで作成されたオブジェクトのみを示します。JavaScript ランタイムによって作成された組み込みオブジェクトは除外されています。オブジェクトの数は、スナップショットの詳細の種類ビューにリンクしています。
オブジェクトの数の相違 (右側の赤または緑のテキスト)。この値は、現在のスナップショットのオブジェクトの数と前のスナップショットのオブジェクトの数との相違を示しています。オブジェクトの数が増加している場合は値が赤で表示され、それ以外の場合は緑で表示されます。オブジェクトの数が同じ場合、値は [相違なし] となります。最初のスナップショットの値は、単に [ベースライン] (灰色のテキスト) です。この値は、スナップショットの相違の種類ビューにリンクしています。
スナップショットの取得時の画面のスクリーンショット。
ヒント
スナップショットの概要に増加または負のサイズ/数の違いが示されていない場合でも、メモリ リークが隠れたままになっていることがあります。この状況は、新しく作成されたオブジェクトの数またはサイズが削除されたオブジェクトの数またはサイズを下回る場合に発生することがあります。たとえば、ガベージ コレクションの結果として発生することがあります。
スナップショットの詳細の表示
スナップショットの詳細ビューでは、各スナップショットのメモリの使用に関する詳細情報を表示できます。
概要ビューからは、スナップショットの概要のリンクをクリックすることでスナップショットの詳細を表示できます。たとえば、スナップショットの概要のヒープ サイズのリンクをクリックすると、既定でドミネーター ビューが開き、スナップショットの詳細が表示されます。
この図は、スナップショットの詳細の種類ビューを示しています。
スナップショットの詳細ビューには、メモリ使用量データに関して次の追加のビューが用意されています。
ドミネーター: 保持されているサイズ順に、ヒープにあるすべてのオブジェクトの一覧を示します。
種類: オブジェクトの種類別に、オブジェクトのインスタンスの数と合計サイズを示します。既定では、これらはインスタンスの数の順に並べ替えられます。
ルート: ルート オブジェクトから子の参照までのオブジェクト ツリーを示します。既定では、子ノードは保持サイズ列を基準に、保持サイズが大きいものから順に並べられます。
DOM: マークアップ (DOM) 要素であるオブジェクトとその保持サイズを示します。既定では、オブジェクトは保持サイズ順に並べ替えられます。
WinRT: JavaScript アプリから参照される Windows マネージ オブジェクトおよびアンマネージ オブジェクトを示します。既定では、オブジェクトは保持サイズ順に並べ替えられます。
ビューのほとんど (たとえば、ドミネーター ビュー) では、同様の種類の値が示されます。これらの値には次の値が含まれます。
[識別子]: オブジェクトを識別する名前。たとえば、HTML 要素に対しては、ID 属性値が表示されます (使用する場合)。
[種類]。オブジェクトの種類名。
[サイズ]: オブジェクトのサイズ (参照されたオブジェクトのサイズは含まれません)。
[保持サイズ]: オブジェクトのサイズと他の親オブジェクトを持たないすべての子オブジェクトのサイズの合計。扱いやすいように、この合計はオブジェクトが保持しているメモリの量を表しており、オブジェクトを削除すると指定された量のメモリが解放されます。
カウント: オブジェクトのインスタンスの数。この値は、種類ビューにのみ表示されます。
スナップショットの相違の表示
JavaScript メモリ アナライザーでは、スナップショットの相違ビューでスナップショットとその前のスナップショットとを比較できます。
概要ビューでは、スナップショットの概要タイルの右上隅にあるドロップダウン リストの別のスナップショットをクリックして、スナップショットの詳細の相違を表示できます。
スナップショットの相違表示では、ドミネーター、型、ルート、DOM オブジェクト、および Windows ランタイム オブジェクトに関する相違情報を表示できます。
スナップショットの相違表示では、2 つのスナップショットの間でヒープに追加されたすべてのオブジェクトが表示されます。相違ルート ビュー (および参照グラフ) の明るい灰色のテキストの色は、そのオブジェクト自体は以前のスナップショットに存在していたが、そのオブジェクト内に以前は存在していなかった子が存在していることを示します。
この図は、スナップショットの相違のドミネーター ビューを示しています。
スナップショットの相違ビューでは、ドミネーター ビューなどのビューはスナップショットの詳細の表示ビューの場合と同じです。スナップショットの相違ビューでは、スナップショットの詳細ビューと同じ種類の値に加えて、次の追加の値が表示されます。
[サイズの相違]: 現在のスナップショットのオブジェクトのサイズと比較のスナップショット (古いスナップショット) のサイズとの相違 (参照されたオブジェクトのサイズは含まれません)。
[保持サイズの相違]: 現在のスナップショットのオブジェクトの保持サイズと比較のスナップショット (古いスナップショット) の保持サイズとの相違。保持サイズには、オブジェクトのサイズと他の親オブジェクトを持たないすべての子オブジェクトのサイズが含まれます。扱いやすいように、この保持サイズはオブジェクトが保持しているメモリの量を表しており、オブジェクトを削除すると指定された量のメモリが解放されます。
[数の相違]: 現在のスナップショットのオブジェクトのインスタンスの数と比較のスナップショットのインスタンスの数の相違。この値は、種類ビューにのみ表示されます。
ルート ビューで表示
ドミネーター、種類、DOM、および WinRT の各ビューでは、特定のオブジェクトと Global オブジェクトとの関係を表示できます。この機能を使用すると、Global のオブジェクト ツリーを検索することなく、ルート ビューで簡単に既知のオブジェクトを見つけることができます。
この機能を使用するには、ドミネーター、種類、DOM、または WinRT ビューで識別子を右クリックし、[ルート ビューで表示] をクリックします。
データのフィルター処理
ドミネーター、種類、DOM、および WinRT ビューでは、特定の識別子を検索してデータをフィルターで除外できます。識別子を検索するには、[識別子フィルター] ボックスに値を入力します。文字の入力を開始すると、入力した文字を含まない識別子がフィルターで除外されます。
それぞれのビューには独自のフィルターがあるため、フィルター処理された情報はビュー間で引き継がれません。
参照の表示
ドミネーター、種類、DOM、および WinRT ビューの下部ペインには、共有された参照を表示するために使用できる参照グラフが含まれています。上部ペインでオブジェクトを選択すると、選択したオブジェクトを指す参照の一覧が参照グラフに表示されます。
同等のオブジェクトを識別するのに役立つ一般的なヘルプを表示するには、上部ペインの右上隅にある設定ドロップダウン リストの [オブジェクト ID の表示] をクリックします。このオプションをクリックすると、[識別子] の一覧のオブジェクトの横にオブジェクト ID が表示されます。同じ ID を持つオブジェクトは共有された参照です。
組み込み値の表示
ドミネーター、種類、DOM、および WinRT ビューでは、組み込みオブジェクトを表示できます。既定では、これらのビューには、アプリで作成するオブジェクトのみが表示されます。これは、不要な情報を除外したり、アプリ関連の問題を特定したりするのに役立ちます。しかし、JavaScript のランタイムによってアプリ用に生成されたすべてのオブジェクトを表示すると便利な場合もあります。JavaScript メモリ アナライザーでは、これらのオブジェクトを表示できます。
これらのオブジェクトを表示するには、ペインの右上隅にある [設定] ボックスの一覧の [組み込み要素の表示] をクリックします。
診断セッション ファイル
診断スナップショットの概要は、関連する詳細ビューと共に、.diagsession ファイルとして保存されます。ソリューション エクスプローラーでは、前の診断のセッションが診断セッション フォルダーに表示されます。ソリューション エクスプローラーで、前のセッションを開く操作、ファイルの削除、またはファイル名の変更を行うことができます。
JavaScript コンソール コマンド
JavaScript メモリ アナライザーは、メモリの問題が発生しているコードを特定するためにコード内で使用できる次の 2 つの JavaScript コンソール コマンドをサポートします。このコマンドをアプリに追加し、メモリ アナライザー以外のコンテキストでアプリを実行した場合は、例外がスローされます (これによって、このコマンドを使用する前にコマンドの有無を確認することができます)。このコマンドは、セッションの開始フェーズの時点では存在しません。
console.takeHeapSnapshot は、JavaScript メモリ アナライザーに表示されるヒープのスナップショットを取得します。
console.profileMark は、概要ビューのメモリ グラフのタイムラインに表示されるプロファイル マーク (ユーザー マークの三角形) を設定します。このコマンドは、1 つの文字列引数を受け取ります。この引数は、イベントの説明を表し、メモリ グラフのツールヒントとして表示されます。この説明は 100 文字以下にする必要があります。
次のコード例に、takeHeapSnapshot プロパティを安全に呼び出す方法を示します。
if (console && console.takeHeapSnapshot) { console.takeHeapSnapshot(); }
次のコード例に、profileMark プロパティを安全に呼び出す方法を示します。
if (console && console.profileMark) { console.profileMark("Initialized"); }
メモリの問題を識別するためのヒント
メモリ使用量の問題を診断する際に、これらのヒントが役に立つ場合があります。
主要なメモリの問題を迅速に識別するには、スナップショットの相違のドミネーター ビューを使用します。
オブジェクトが全体的なメモリ階層内のどこで参照されているかを識別するには、ルート ビューで表示を使用します。
メモリの問題の原因を特定するのが困難な場合は、さまざまなビュー (ドミネーター、種類など) を使用して、関連オブジェクトや種類などで共通する点を探します。
問題を特定するうえでコードを一時的に変更することが役に立つかどうかを検討します。たとえば、次の操作を行います。
メモリ アナライザー用の JavaScript コンソール コマンドである console.takeSnapshot と console.profileMark を使用します。
これらのコマンドを使用すると、手動で [ヒープ スナップショットの作成] をクリックしても特定できない問題を特定することができます。
JavaScript メモリ アナライザー ビュー (たとえば、ドミネーター ビュー) で簡単に見つけることができるテスト オブジェクトを作成します。たとえば、非常に大きいオブジェクトを別のオブジェクトにアタッチすることで、特定のオブジェクトまたは要素に対してガベージ コレクションが行われたかどうかを確認できます。
新しいページへの移動が発生した後も誤ってメモリに保持されているオブジェクトを検索します。これは、一般的なメモリの問題の原因です。たとえば、URL.CreateObjectUrl 関数の不適切な使用により、この問題が発生する可能性があります。