2013-03-22 36 views
0

我正在研究一個基準測試工具,其中包括測量執行操作的外部過程使用的時間和內存。我最感興趣的是峯值可分頁內存大小(a.k.a. PageFileBytesPeak性能計數器/ Process.PeakPagedMemorySize64 /峯值專用字節)。這是一個.NET項目,所以純.NET解決方案會更好,但這很可能不是一種可能性。測量過程高峯內存使用率驗屍

這裏的問題是我不知道進程退出前的峯值內存使用情況。當過程不再存在時,我無法讀取過程的性能計數器。所以我可以在流程運行的時候輪詢它。

然而,這並不是優選的,因爲如果我經常輪詢,我會干擾該過程完成其工作所花費的時間,並且如果輪詢結果太少,結果將不準確(該過程很可能會中斷它的峯值內存使用權在退出之前)。所以我希望有一些方法來做到這一點確實比我想出了迄今爲止的解決方案少哈克:

  1. 進樣DLL注入過程中,通過對DLL_PROCESS_DETACH IPC機制報告的價值。
  2. 在執行真正的ExitProcess之前,在目標進程中修補/掛鉤ExitProcess,通過IPC機制報告值。
  3. 假裝爲調試器,測量EXIT_PROCESS_DEBUG_EVENT上的值(在調用ContinueDebugEvent之前,內核不會清理進程)。

回答

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; 
} 
1

讀取現存的PerfMon計數器應該是一個非常低的開銷操作,因爲計數器通常(可能總是不確定)使用共享內存塊(映射文件)來實現。

我會用運行時可配置的時間間隔來實現輪詢,如果您發現這會影響您的應用程序,那麼只能使用更復雜的技術。如果您想首先檢查它,請設置PerfMon以監視感興趣的計數器,並查看在可用刷新間隔下運行時是否會導致應用程序死機。

+0

即使忽略與使用我還是有問題的過程可能最後一次量子內分配大量內存的問題時干擾的可能性,這將意味着我不能如果我的代碼被安排在與分配內存的線程相同的內核中,無論我輪詢的速度如何,都可以看到它。這個操作可能需要不到200ms才能完成,而在服務器系統上的時間約爲180ms,我甚至沒有機會在流程啓動和退出之間獲得時間片。 – poizan42 2013-03-22 17:29:16

+0

我同意,如果您擔心流程關閉(或民意調查之間)的巨大峯值,那麼投票是不夠的。我只是想知道這是否真的像你想象的那樣是一個問題,考慮到它的額外成本。 – 2013-03-22 17:49:49

+0

不幸的是,這是一個基準工具,其主要目的是基準新的後端(它實際上是測試不同的引擎進行PDF轉換和連接,但這不是真的與問題相關),所以你可能是對的,它贏了不需要,但我事先不知道。似乎我將不得不去dll注入路線。 – poizan42 2013-03-25 12:04:35