0

私は、操作を実行する外部プロセスによって使用される時間とメモリを測定するベンチマーク ツールに取り組んでいます。私は主にページング可能メモリのピーク サイズ (別名 PageFileBytesPeak パフォーマンス カウンター / Process.PeakPagedMemorySize64 / ピーク プライベート バイト) に関心があります。これは .NET プロジェクトであるため、純粋な .NET ソリューションが望ましいですが、これはおそらく不可能です。

ここでの問題は、プロセスが終了する前にピーク時のメモリ使用量がわからないことです。プロセスが存在しない場合、そのプロセスのパフォーマンス カウンターを読み取ることができません。そのため、プロセスの実行中に代わりにポーリングすることができます。

ただし、ポーリングの頻度が高すぎると、プロセスが作業を完了するのにかかる時間に干渉するため、これは好ましくありません。また、ポーリングの頻度が低すぎると、結果が正確ではなくなります (プロセスがメモリ使用量のピークに達する可能性が高くなります)。出る直前)。したがって、これまでに思いついたソリューションよりもハックしにくい、確実に行う方法があることを願っています。

  1. DLL をプロセスに挿入し、DLL_PROCESS_DETACH の IPC メカニズムを介して値を報告します。
  2. ターゲット プロセスの ExitProcess にパッチ/フックを適用し、実際の ExitProcess を実行する前に IPC メカニズムを介して値を報告します。
  3. デバッガーのふりをして、EXIT_PROCESS_DEBUG_EVENT の値を測定します (プロセスは、ContinueDebugEvent が呼び出される前にカーネルによってクリーンアップされません)。
4

2 に答える 2

1

既存の PerfMon カウンターの読み取りは、特にオーバーヘッドが非常に少ない操作である必要があります。カウンターは通常(おそらく常に?確かではありませんが)共有メモリのブロック(マップされたファイル)を使用して実装されるため、操作したいシステムカウンターの場合。

実行時に構成可能な間隔でポーリングを実装し、これがアプリケーションに重大な影響を与えていることがわかった場合にのみ、より複雑な手法に頼ります。これを最初に健全性チェックする場合は、対象のカウンターを監視するように PerfMon を設定し、使用可能な更新間隔で実行しているときにアプリケーションが強制終了されるかどうかを確認します。

于 2013-03-22T17:06:28.837 に答える
1

GetProcessMemoryInfoは、アクティブなハンドルがある限り、プロセスが終了した後でも機能することがわかりました。ただし、必要になった場合でも、仮想メモリの使用量はこの方法では利用できません。

値のサイズは呼び出し元のプロセスのビット数に依存するため、32 ビット プロセスが 64 ビット プロセスのメモリ使用量を測定すると、値がオーバーフローする可能性があることに注意してください。

例:

[DllImport("psapi.dll", SetLastError=true)]
static extern bool GetProcessMemoryInfo(IntPtr hProcess, out PROCESS_MEMORY_COUNTERS counters, int size);

[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_MEMORY_COUNTERS
{
    public uint cb;
    public uint PageFaultCount;
    public UIntPtr PeakWorkingSetSize;
    public UIntPtr WorkingSetSize;
    public UIntPtr QuotaPeakPagedPoolUsage;
    public UIntPtr QuotaPagedPoolUsage;
    public UIntPtr QuotaPeakNonPagedPoolUsage;
    public UIntPtr QuotaNonPagedPoolUsage;
    public UIntPtr PagefileUsage;
    public UIntPtr PeakPagefileUsage;
}

public long BenchmarkProcessMemoryUsage(string fileName, string arguments)
{
    ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
    startInfo.UseShellExecute = false;
    Process process = Process.Start();
    process.WaitForExit();
    PROCESS_MEMORY_COUNTERS counters;
    if (!GetProcessMemoryInfo(process.Handle, out counters, Marshal.SizeOf(typeof(PROCESS_MEMORY_COUNTERS))))
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    return (long)counters.PeakPagefileUsage;
}
于 2013-03-26T16:55:37.567 に答える