dotMemory 2018.3ヘルプ

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

ピンニングハンドル

Interaction of managed and unmanaged code is an additional problem for the Garbage Collector. For example, you need to pass an object from the managed heap to, say, an external API library. As a small object heap is compacted during collection, the object can be moved. This is a problem for the unmanaged code if it relies on the exact object location. One of the solutions is to fix the object in the heap. In this case, GC gets a pinning handle to the object which implies that the object cannot be moved. Thus, if you see the ピンニングハンドル type, then probably the object is retained by some unmanaged code. For example, the App object always has a pinned reference.

Pinning handle root

There is one more case when you can see a ピンニングハンドル in a snapshot. Sometimes, it is not possible to correctly identify a static reference: Instead of a 静的リファレンス root, you may see an array of objects Object[] retained by the ピンニングハンドル root. This is a true representation of how static references work.

Pinning handle root instead of a static reference root

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

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

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

RefCounted handle root

弱いハンドル

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

Weak handle root

レギュラーハンドル

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

Regular handle root
最終更新日: 2019年3月15日