3

我試圖實現一個性能監視工具,我想監視基本的東西,如內存和CPU。什麼是查詢過程性能計數器的最高性能方法?

我試圖通過使用性能計數器這樣做,因爲我相信這是在C#查詢處理性能的「正確」的方式,這是一些示例代碼:

class Program 
    { 
     static void Main(string[] args) 
     { 
      while (true) 
      { 
       var pcs = Process.GetProcesses() 
        .Select(p => new PerformanceCounter("Process", "Working Set - Private", p.ProcessName)); 

       var sw = Stopwatch.StartNew(); 

       foreach (var pc in pcs) 
        pc.NextValue(); 

       Console.WriteLine($"Time taken to read {pcs.Count()} performance counters: {sw.ElapsedMilliseconds}ms"); 

       Thread.Sleep(1000); 
      } 
     } 
    } 

enter image description here

所以顯然〜12.5毫秒來查詢我的系統上的進程是無法接受的慢。它應該如何完成?

我已經問一個相關的問題在這個帖子:Performance Counter read access very slow - How does Task Manager do it?

但我知道我不是在該職位不夠具體和問錯了qestion。我真正想知道的是,如何才能做到我想用性能計數器做的事情,還是根本無法做到?

EDIT1

我運行Windows 10 Pro的1607 - 構建14393.479

+0

你總是可以[使用原始的Win32 API](http://mjs5.com/2016/06/05/c-get-basic-memory-information-using-getperformanceinfo-api/)..或運行一個並行的任務很少。 – stuartd

+1

順便提一句,[Memory Performance MSDN page](https://msdn.microsoft.com/en-us/library/windows/desktop/aa965225(v = vs.85).aspx)表示_「內存性能信息可用從內存管理器到系統性能計數器以及諸如GetPerformanceInfo,GetProcessMemoryInfo和GlobalMemoryStatusEx等函數,諸如Windows任務管理器,可靠性和性能監視器以及Process Explorer工具等應用程序使用性能計數器來顯示系統的內存信息併爲個人進程。「# – stuartd

+0

@stuartd你知道什麼,我完全忘記了線程。我確實可以並行運行它們!我想知道對性能會有什麼影響.. – mikeysee

回答

10

Windows是一個有點臭名昭著大約是緩慢的,只要你做一臺機器上所有正在運行的進程的東西。但是這太過分了。 PerformanceCounter的狀態有些爛,我從this question得到第一個提示。有些事情,你可以在自己的測試程序,通過改變Console.WriteLine命令()調用輕鬆地可視化:

Time taken to read 124 performance counters: 1633ms, 15 collections 
Time taken to read 124 performance counters: 923ms, 30 collections 
Time taken to read 124 performance counters: 928ms, 45 collections 
Time taken to read 124 performance counters: 934ms, 59 collections 
Time taken to read 124 performance counters: 922ms, 74 collections 
Time taken to read 124 performance counters: 925ms, 89 collections 
...etc 

或者換句話說,一個垃圾收集:我的機器上

Console.Write($"Time taken to read {pcs.Count()} performance counters:"); 
    Console.WriteLine($"{sw.ElapsedMilliseconds}ms, {GC.CollectionCount(2)} collections"); 

輸出對於PerformanceCounter.NextValue()的每個〜8調用。哎喲。是的,這會讓你的計劃陷入困境。

這是非常奇怪的行爲,說得很溫和。我在PerformanceCounter類本身找不到任何好的提示,代碼看起來很無辜。在很難看到的大量非託管代碼中(C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ PerfCounter.dll),但查看它的依賴關係並不能提供令人信服的證據證明它是負責。這在v2.0.50727和v4.0.30319運行版本上都會發生,所以V4.x中的一個不幸的破解不會輕易解釋它。它不是8的很好的倍數,所以一個簡單的計數器強制終結器運行並不容易解釋它。這不是本機性能計數器,使用WMI查詢它不會觸發任何收集。它不是特定於內存計數器,查詢,比如說「線程數」也可以。可能與Windows版本有關,我的Win10版本是1607(不能輕易測試另一個版本)。

微軟需要介入此。我鏈接的問題的作者似乎創建了一個bug feedback report for it,我添加了這個Q + A作爲支持證據。留意反饋報告,投票表決,希望他們會開始關注。或者如果您不想等待,請直接與Microsoft支持部門聯繫。


同時,您可以使用System.Management命名空間。該WMI代碼Creator實用程序是非常方便的自動生成代碼:

... 
using System.Management;  // Project > Add Reference required 

    public static void QueryWorkingset() { 
     ManagementObjectSearcher searcher = 
      new ManagementObjectSearcher("root\\CIMV2", 
       "SELECT Name, WorkingSetPrivate FROM Win32_PerfRawData_PerfProc_Process"); 
     foreach (ManagementObject queryObj in searcher.Get()) { 
      Console.WriteLine("{0}: {1}", queryObj["Name"], queryObj["WorkingSetPrivate"]); 
     } 
    } 

仍然沒有速度妖,需要每個進程的約1.0毫秒我的機器上。但是不像PerformanceCounter那樣刻錄100%核心,也不會強制收集。

+1

謝謝先生,這已經非常有幫助。我將更新我的原始帖子與我的Windows版本(10),並將將我的聲音添加到該錯誤報告中,並通過我的某個渠道與Microsoft聯繫。 我已經將此答案標記爲正確,直到我們有正式解決方案。 – mikeysee