dotMemory 2019.1ヘルプ

GCルートの分析

オブジェクトの保存パスは、常にGCルートで始まります。ガベージコレクタの観点からは、rootは収集してはいけないし収集しないオブジェクトへの参照です。これが根を保持グラフを構築するための唯一の出発点にします。「誰がオブジェクトを保持しているか」の間、ルートタイプを理解することは非常に重要です。分析。保存パスを調べても、オブジェクトがまだメモリ内にある理由がわかりません。この場合、GCのルートを見ることは理にかなっています。例: RefCountedハンドルは、オブジェクトが管理されていないCOMライブラリーによって保持されているという手がかりを与えます。

.NET フレームワークには、4つのルートタイプがあります。

  • スタック参照 : ローカルオブジェクトへの参照そのようなルートはメソッド実行中に生きます。

  • 静的参照 : 静的オブジェクトへの参照これらのルートはアプリドメインのライフタイム全体を生きます。

  • ハンドル : 通常、これらは管理対象コードと管理対象外コード間の通信に使用される参照です。そのようなルートは、少なくともアンマネージコードが「管理された」オブジェクトを必要とするまで存続しなければなりません。

  • ファイナライザの参照 : ファイナライズされるのを待っているオブジェクトへの参照。これらのルートはファイナライザが実行されるまで生き続けます。

保存パスのルートを分析するには、オブジェクト保存パスを表示する任意のdotMemoryビュー(同様の保持によるグループ最短経路によるグループキー保持パス、およびルートへの最短経路)を使用します。dotMemoryによって識別されるすべてのルートタイプは、上記のリストに記載されているカテゴリの1つに分類されます。

通常のローカル変数

これは、メソッド内で宣言されたローカル変数(スタック上の変数)です。この変数への参照は、メソッドの有効期間中にルートになります。たとえば:

static void Main() { ... var collection = new Collection <int>(); ... }
Regular local variable root

リリースビルドでは、rootの存続期間が短くなる可能性があることに注意してください。JITは変数が不要になった直後にその変数を破棄できます。

静的リファレンス

CLRが静的オブジェクト(クラスメンバー、変数、またはイベント)と一致すると、このオブジェクトのグローバルインスタンスが作成されます。オブジェクトにはアプリのライフタイム全体を通してアクセスできるため、静的オブジェクトはほとんど収集されません。静的オブジェクトへの参照は、主要なルートタイプの1つです。

class StaticClass { public static Collection<string> StCollection; }

コレクションが初期化された後、CLRはコレクションの静的インスタンスを作成します。インスタンスへの参照は、アプリケーションドメインの有効期間中に存在します。

Static reference root

静的オブジェクトがフィールドを介して参照されると、dotMemoryはフィールドの名前を表示します。

もちろん、「名前のない」静的参照も発生する可能性があります。そのようなルートの最も明白な例は、メソッド内で宣言された文字列への参照です。

static void Main() { ... string A = "This is a string"; ... }
Static reference root

上記の例では、通常のローカル変数参照もCLRによって作成されています。しかし、さらなる分析を簡単にするために、dotMemoryはあなたにこの根を見せていません。

F-到達可能キュー/ファイナライズキュー

CLRは、管理されていないリソースを解放するための便利なメカニズム、つまりファイナライズパターンを提供します。 System.Object 型は、オブジェクトのメモリが回収される前にガベージコレクタによって呼び出される仮想メソッド Finalize (ファイナライザとも呼ばれます)を宣言します。通常、管理されていないリソースを解放するためにこのメソッドをオーバーライドします。ファイナライザを持つオブジェクトはすべてファイナライズキューに入れられます(dotMemoryではこれらのオブジェクトはファイナライズキュールートを持ちます)。ガベージコレクションが行われると、GCはそのようなオブジェクトをFinalizationキューから見つけますが、そのファイナライザを直接実行することはしません。代わりに、GCはオブジェクトをF到達可能キュー(dotMemoryのF到達可能キュールート)に置き、別のファイナライゼーションスレッドでファイナライザーを実行します(ファイナライザーは潜在的に任意の量のコードを実行できるため、パフォーマンスのためにこれらのすべてが行われます)。)次のGCでは、F到達可能キュー内のオブジェクトはガベージコレクションされます。記述されているパターンには欠点があり、それがdotMemoryが特別なファイナライズ可能オブジェクト インスペクションを提供する理由です。

メモリプロファイリングの性質上、dotMemoryはスナップショットが取られる前に常にフルGCを実行します。dotMemoryで撮影したスナップショットにファイナライズキュールートを持つオブジェクトが見つからないのはそのためです。このルートタイプは、ローメモリダンプでのみ可能です。

F-Queue root

ピンニングハンドル

マネージコードとアンマネージドコードの相互作用は、ガベージコレクタにとってもう1つの問題です。例:マネージヒープからオブジェクトを、たとえば外部APIライブラリーに渡す必要があります。小さいオブジェクトのヒープは収集中に圧縮されるため、オブジェクトを移動できます。オブジェクトの正確な場所に依存している場合、これはアンマネージコードにとって問題です。解決策の1つは、ヒープ内のオブジェクトを修正することです。この場合、GCはオブジェクトへの固定ハンドルを取得します。これは、オブジェクトを移動できないことを意味します。ピンニングハンドルルートが表示された場合は、おそらくオブジェクトは管理されていないコードによって保持されています。たとえば、App オブジェクトには常に固定参照があります。

Pinning handle root

スナップショットにピンニングハンドルが表示される場合があります。場合によっては、静的参照を正しく識別できないことがあります。静的リファレンスルートの代わりに、ピンニングハンドルルートによって保持されているオブジェクト Object[] の配列が表示されることがあります。これは、静的参照がどのように機能するかの真の表現です。

Pinning handle root instead of a static reference root

内部ローカル変数

管理対象オブジェクトはガベージコレクション中に移動できるため(ピンニングハンドルを参照)、ネイティブポインタを使用してヒープ上のそれらの位置を追跡することはできません。そのような場合は、内部ポインタ(英語)を使用できます。内部ポインタは、参照型の内部へのポインタを宣言しますが、オブジェクト自体には宣言しません。オブジェクトを保持している内部ローカル変数ルートが見えたら、おそらくこのオブジェクトの内側を指す内部ポインタがあります。例として、MSDN(英語)を参照してください。

Interior local variable

リフレッシュされたハンドル

オブジェクトの参照カウントが特定の値である場合、ルートはガベージコレクションを防ぎます。オブジェクトがCOM相互運用機能を使用してCOMライブラリーに渡されると、CLRはこのオブジェクトへのRefCountedハンドルを作成します。COMはガベージコレクションを実行できないため、このルートが必要です。代わりに、参照カウントを使用します。オブジェクトが不要になった場合、COMはカウントを0に設定します。これは、RefCountedハンドルがルートではなくなり、オブジェクトを収集できることを意味します。

RefCountedハンドルと表示された場合、おそらく、オブジェクトはアンマネージコードの引数として渡されます。

RefCounted handle root

弱いハンドル

他のルートとは対照的に、ウィークハンドルは参照されているオブジェクトがガベージコレクションを妨げることはありません。オブジェクトはいつでも収集できますが、それでもアプリケーションからアクセスできます。そのようなオブジェクトへのアクセスは、WeakReference タイプの中間オブジェクトを介して実行されます。このようなアプローチは、キャッシュのような一時的なデータ構造を扱うときに非常に効率的です。弱い参照は完全なガベージコレクションに耐えられないため、弱い参照ハンドルは他のハンドルとの組み合わせでしか使用できません。例:弱い、RefCountedハンドル

Weak handle root

レギュラーハンドル

ハンドル・タイプが未定義の場合、dotMemoryはそれをレギュラーハンドルとしてマークします。通常、これらはアプリのライフタイム全体を通して必要とされるシステムオブジェクトへの参照です。例: OutOfMemoryException オブジェクトその収集を防ぐために、環境は通常のハンドルを通してオブジェクトを参照します。

Regular handle root
最終更新日: 2019年5月31日

関連ページ:

同様の保持によるグループ

同様の保持によるグループビューは、保存パスの類似性によってオブジェクトをグループ化します。オブジェクトセットごとに、ビューにはルートへの最短パスが2つ表示されます。dotMemoryは、さまざまな最短パスの中から、互いに最も異なる2つのパスのみを選択します。同様の保持によるグループビューでは、同じタ...

最短経路によるグループ

最短経路によるグループビューには、選択したオブジェクトセットの最短保持パスが表示されます。複数のルートからオブジェクトにアクセスできる場合、dotMemoryは最も近いルートまでのパスを1つだけ表示します。他のすべてのパスは、簡単にするために破棄されます。このビューを使用すると、オブジェクトがどのよ...

キー保持パス

キー保持パスビューに、インスタンスの保存パスがいくつか表示されます。より具体的には、あなたにお互いに最も大きく異なるパスだけを示します。これが、このビューの主な違いです。他の「保持ビュー」と比較すると、主に最短の保持パスを表示することを目的としています。以下の例を考えてみましょう。Dオブジェクトのキ...

ルートへの最短経路

ルートへの最短経路ビューグループには、アプリケーションのルートからインスタンスへの最短パスが表示されます。ルートごとに1つの最短パスがあります。便宜上、dotMemoryは、プレーンリスト(最短経路)とツリー(結合された最短経路)の2通りの方法でパスを表示します。特定の方法を選択するには、ビューのリ...

自動インスペクション

dotMemoryは、以下のメモリの問題を自動的に検出します。文字列重複:既存のものを再利用するのではなく、同じ値を持つ文字列を繰り返し作成することは、メモリを無駄にします。dotMemoryは重複した文字列を検出し、無駄なメモリ量を示します。オブジェクトを分析するにはインスペクションヘッダーのリン...

メモリトラフィックの分析

トラフィック分析は、アプリのメモリ使用量を効果的に判断するための主要な手段です。過度の割り当てやガベージコレクションは、メモリ管理のオーバーヘッドが大きくなる可能性があります。例:時間の経過と共に更新されるべきオブジェクトの配列があります。必要なプロパティーを持つ新しいインスタンスを作成するか、既存...