アプリケーション ドメインのリソース監視

アプリケーション ドメインのリソース監視 (ARM) を使用して、ホストでアプリケーション ドメインによる CPU とメモリの使用状況を監視できます。 これは、実行時間の長いプロセスで多数のアプリケーション ドメインを使用する ASP.NET などのホストに役立ちます。 問題のあるアプリケーションを特定できる場合に限り、ホストは、プロセス全体のパフォーマンスに悪影響を与えるアプリケーションのアプリケーション ドメインをアンロードできます。 ARM は、このような意思決定を支援するために使用できる情報を提供します。

たとえば、ホスティング サービスでは、ASP.NET サーバー上で多くのアプリケーションが実行されている可能性があります。 プロセス内の 1 つのアプリケーションでメモリ消費量やプロセッサ時間が過度に増え始めた場合、ホスティング サービスは ARM を使用して問題の原因となっているアプリケーション ドメインを特定できます。

ARM は十分に軽量なので、ライブ アプリケーションで使用できます。 情報には、Windows (ETW) のイベント トレースを使用してアクセスするか、マネージド API またはネイティブ API を使用して直接アクセスできます。

リソース監視を有効にする

ARM を有効にする方法は 4 つあります。共通言語ランタイム (CLR) の起動時に構成ファイルを提供する方法、アンマネージド ホスティング API を使用する方法、マネージド コードを使用する方法、または ARM ETW イベントをリッスンする方法です。

ARM が有効になるとすぐに、プロセスのすべてのアプリケーション ドメイン上でデータの収集が開始されます。ARM が有効になる前にアプリケーション ドメインが作成された場合、アプリケーション ドメインの作成時ではなく、ARM が有効になったときに累積データが開始されます。ARM を有効にした後に無効にすることはできません。

  • CLR 起動時に ARM を有効にするには、<appDomainResourceMonitoring> 要素を構成ファイルに追加し、enabled 属性を true に設定します。 false の値 (既定) は、起動時に ARM は有効ではないことのみを意味します。他のアクティブ化メカニズムのいずれかを使用して、後で有効にすることができます。

  • ホストは、ICLRAppDomainResourceMonitor ホスティング インターフェイスを要求することで ARM を有効にすることができます。 このインターフェイスが正常に取得されると、ARM が有効になります。

  • マネージド コードでは、static (Visual Basic では Shared) AppDomain.MonitoringIsEnabled プロパティを true に設定して ARM を有効にすることができます。 プロパティが設定されるとすぐに、ARM が有効になります。

  • 起動後に ETW イベントをリッスンして ARM を有効にすることができます。 AppDomainResourceManagementKeyword キーワードを使用してパブリック プロバイダー Microsoft-Windows-DotNETRuntime を有効にすると、ARM が有効になり、すべてのアプリケーション ドメインのイベント生成が開始されます。 データをアプリケーション ドメインとスレッドに関連付けるには、ThreadingKeyword キーワードを使用して Microsoft-Windows-DotNETRuntimeRundown プロバイダーを有効にする操作も必要です。

ARM の使用

ARM は、アプリケーション ドメインに使用される合計プロセッサ時間と、メモリ使用に関する 3 種類の情報を提供します。

  • アプリケーション ドメインの合計プロセッサ時間 (秒単位) : アプリケーション ドメインの有効期間中に実行されていたすべてのスレッドについて、オペレーティング システムから報告されたスレッド時間を合計して計算されます。 ブロックされているスレッドまたはスリープ状態のスレッドは、プロセッサ時間を使用しません。 スレッドがネイティブ コードを呼び出すときに、スレッドがネイティブ コードに費やす時間は、呼び出しが行われたアプリケーション ドメインの計算に含まれます。

  • 有効期間中にアプリケーション ドメインによって行われたマネージドされた割り当ての合計 (バイト単位) : 割り当てられたオブジェクトの有効期間は短いことがあるので、割り当ての合計にアプリケーション ドメインによるメモリ使用量が反映されない場合もあります。 ただし、アプリケーションが膨大な数のオブジェクトを割り当ててから解放すると、割り当てのコストが大幅に高くなる可能性があります。

  • アプリケーション ドメインによって参照され、最新の完全なブロッキング コレクションの後に残っているマネージド メモリ (バイト単位) : この数値は完全なブロッキング コレクションの後にのみ正確になります。 (これは、バックグラウンドで発生し、アプリケーションをブロックしない同時コレクションとは対照的です)。たとえば、GC.Collect() メソッドのオーバーロードによって、完全なブロッキング コレクションが実行されます。

  • プロセスによって参照され、最新の完全なブロッキング コレクションの後に残っている合計マネージド メモリ (バイト単位) : 個々のアプリケーション ドメインに残っている​​メモリをこの数値と比較できます。

完全なブロッキング コレクションが発生したときの判断

残っているメモリの計算が正確かどうかを判断するには、完全なブロッキング コレクションがいつ発生したかを把握する必要があります。 これを行う方法は、ARM 統計を調べるために使用する API によって異なります。

マネージド API

AppDomain クラスのプロパティを使用する場合は、GC.RegisterForFullGCNotification メソッドを使用して完全なコレクションの通知を登録できます。 コレクションのアプローチではなく、コレクションの完了を待機するので、使用するしきい値は重要ではありません。 次に、GC.WaitForFullGCComplete メソッドを呼び出すことができます。このメソッドは、完全なコレクションが完了するまでブロックされます。 ループ内でメソッドを呼び出し、メソッドから復帰するたびに必要な分析を実行するスレッドを作成できます。

また、GC.CollectionCount メソッドを定期的に呼び出して、世代 2 コレクションの数が増加しているかどうかを確認することもできます。 ポーリング頻度によっては、この手法では完全なコレクションの発生が正確に示されない場合があります。

ホスティング API

アンマネージ ホスティング API を使用する場合、ホストは CLR に IHostGCManager インターフェイスの実装を渡す必要があります。 コレクションの実行中に中断されたスレッドの実行を再開すると、CLR は IHostGCManager::SuspensionEnding メソッドを呼び出します。 CLR は、完全なコレクションの生成をメソッドのパラメーターとして渡します。そのため、ホストはコレクションが完全か部分的かを判断できます。 IHostGCManager::SuspensionEnding メソッドを実装すると、残っているメモリのクエリを実行して、カウントが更新された場合にすぐに取得することができます。

関連項目