ASP.NET ワーカー プロセス ID からパフォーマンス カウンター インスタンス名 (w3wp#XX) を取得する
-
02-07-2019 - |
質問
.NET/Process パフォーマンス カウンターを使用して、Web ページにいくつかのメモリ統計 (ワーキング セット、GC など) を表示したいと考えています。残念ながら、そのサーバー上に複数のアプリケーション プールがある場合、それらはインデックス (#1、#2 など) を使用して区別されますが、(私が持っている) プロセス ID をその #xx インデックスと照合する方法がわかりません。(ASP.NET Web ページから) プログラムによる方法はありますか?
解決
Google での最初のヒット:
「W3wp#1」のような名前を持つ複数の CLR パフォーマンス カウンターが表示されます。
複数のASP.NETワーカープロセスが実行されている場合、共通言語ランタイム(CLR)パフォーマンスカウンターには、「W3WP#1」または「W3SP#2」などに似た名前があります。これは、.NET Framework 2.0で改善され、.NET CLRメモリパフォーマンスオブジェクトにカウンターという名前のプロセスIDが含まれています。このカウンターは、インスタンスのプロセスIDを表示します。このカウンターを使用して、プロセスに関連付けられているCLRパフォーマンスカウンターを決定できます。
また KB 281884:
デフォルトでは、パフォーマンスモニター(perfmon.msc)は、次の方法でプロセスを列挙することにより、同じ名前の複数のプロセスを表示します。
工程#1 工程#2 工程#3
パフォーマンスモニターは、プロセスID(PID)を次の方法で名前に追加することにより、これらのプロセスを表示することもできます。
プロセス_PID
他のヒント
private static string GetProcessInstanceName(int pid)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process",
"ID Process", instance, true))
{
int val = (int) cnt.RawValue;
if (val == pid)
{
return instance;
}
}
}
throw new Exception("Could not find performance counter " +
"instance name for current process. This is truly strange ...");
}
chiru による例は、特定のケースでは機能しません。同じ名前の同じプログラムの 2 つのバージョンがあり、1 つは .net ではなく、非 .net バージョンの後に .net バージョンを開始する場合です。.Net バージョンには application#1 という名前が付けられますが、この名前を使用して CLR perf カウンタにアクセスすると、カウンタのインスタンス名には #1 が付いていない名前が付けられるため、エラーが発生します。
ニック。
レジストリ設定の変更は非常に簡単に見えますが、残念なことに、ほとんどの人はサーバー上で変更を行う権限を持っていません (または、変更したくありません!)。その場合、ちょっとした回避策があります。これについてブログに書きました ここ.
以前に回答されているのは承知していますが、完全に機能するコードを目的として、この解決策を投稿します。このコードは、このチェーンで M4N によって送信されたメソッドに基づいていることに注意してください。
public static long GetProcessPrivateWorkingSet64Size(int process_id)
{
long process_size = 0;
Process process = Process.GetProcessById(process_id);
if (process == null) return process_size;
string instanceName = GetProcessInstanceName(process.Id);
var counter = new PerformanceCounter("Process", "Working Set - Private", instanceName, true);
process_size = Convert.ToInt32(counter.NextValue()) / 1024;
return process_size;
}
public static string GetProcessInstanceName(int process_id)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true))
{
int val = (int)cnt.RawValue;
if (val == process_id)
return instance;
}
}
throw new Exception("Could not find performance counter ");
}
また、同じプロセスの複数のインスタンスの合計メモリを取得したい場合は、上記のメソッドと次のメソッドを併用します。
public static long GetPrivateWorkingSetForAllProcesses(string ProcessName)
{
long totalMem = 0;
Process[] process = Process.GetProcessesByName(ProcessName);
foreach (Process proc in process)
{
long memsize = GetProcessPrivateWorkingSet64Size(proc.Id);
totalMem += memsize;
}
return totalMem;
}