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の存続期間が短くなる可能性があることに注意してください。JITは変数が不要になった直後にその変数を破棄できます。

静的リファレンス

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

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

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

static reference 1

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

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

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

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

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

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

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

roots fqueue

ピンニングハンドル

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

pinning handle

注: fixed ブロックを使用して意図的にオブジェクトを固定することもできます。

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

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

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

refcounted handle

弱いハンドル

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

weak handle

レギュラーハンドル

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

regular handle
最終更新日: 2018年12月18日