2016-06-23 41 views
0

我想實現一個監視當前正在運行的進程的系統。系統獲取有關高負載(CPU,內存等)的信息。我調查了兩個命名空間。它是System.Diagnostics和System.Management。 首先,我寫了一個類來顯示所有正在運行的進程的名稱,ID和CPU負載。性能跟蹤的最佳做法是什麼? System.Diagnostics或System.Management?

class Program 
{ 
    static void Main() 
    { 
     Console.WriteLine("--------------using System.Diagnostics---------------------"); 
     SysDi(); 

     Console.WriteLine("----using System.Diagnostics CPU load always zero----------"); 

     //Here CPU load always zero 
     SysDiCpuZero(); 

     Console.WriteLine("--------------using System.Management---------------------"); 
     Vmi(); 

    } 


    static void Vmi() 
    { 
     try 
     { 
      var searcher = new ManagementObjectSearcher("root\\CIMV2", 
       "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process"); 

      foreach (var queryObj in searcher.Get()) 
      { 
       Console.WriteLine($"Process: {queryObj["Name"]} " + 
            $"ID: {queryObj["CreatingProcessID"]} " + 
            $"CPU load: {queryObj["PercentProcessorTime"]}"); 
      } 
     } 
     catch (ManagementException e) 
     { 
      Console.WriteLine("An error occurred while querying for WMI data: " + e.Message); 
     } 
    } 

    static void SysDi() 
    { 
     var processlist = Process.GetProcesses(); 
     var counters = new List<PerformanceCounter>(); 
     foreach (var theprocess in processlist) 
     { 
      var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName); 

      counter.NextValue(); 
      counters.Add(counter); 
     } 

     var i = 0; 


     Thread.Sleep(10); 
     foreach (var counter in counters) 
     { 
      Console.WriteLine($"Process: {processlist[i].ProcessName} " + 
           $"ID: {processlist[i].Id} " + 
           $"CPU load: {Math.Round(counter.NextValue(), 5)}"); 
      ++i; 
     } 
    } 

    static void SysDiCpuZero() 
    { 
     var processlist = Process.GetProcesses(); 

     foreach (var theprocess in processlist) 
     { 
      var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName); 
      counter.NextValue(); 

      Console.WriteLine($"Process: {theprocess.ProcessName} " + 
       $"ID: {theprocess.Id} " + 
       $"CPU load: {Math.Round(counter.NextValue(), 5)}"); 
     } 
    } 
} 

此外,我注意到在不同的命名空間中,相同的屬性具有不同的值。 此外,System.Diagnostic比System.Management快,但方法SysDi()與CPU加載數據看起來不清楚。

有什麼更好的使用在我的情況?我應該遵循什麼標準來選擇?

+1

根據您的平臺(Windows版本等)和需求,至少還有兩點需要考慮:性能計數器和ETW。 –

+0

Hmya,流程類不會讓你走得很遠。更好的是通常由椅子和鍵盤之間的內容決定,而不是框架類。實際上只需要'SELECT Name'時使用'SELECT *'並不會更好。這些都是一次性類,但你不處理它們。如果您需要代碼審查,請使用http://codereview.stackexchange.com/。 –

+0

使用ETW/xperf/WPR。 – magicandre1981

回答

1

使用你的代碼,在這裏它包裹StopWatch的是結果(MS):

WithWMI: 4ms 
WithoutWMI: 2ms 

這是隻是一個單一的電話,所以使用Process.GetProcess()是快,但它也更容易讀取(在我的意見),你不必擔心魔術字符串(例如查詢)。

運行它幾次後,似乎使用Process.GetProcess()更快,在一些運行中它們都花費相同的時間,但通常Process.GetProcess()更快購買幾個毫秒。

另外,如果您不必使用WMI,那麼不要,WMI已知會變慢。

而且似乎查詢ManagementObjectSearcher時,它可以使用更多的CPU相比,調用Process.GetProcess(),我致電他們兩個10000次注意到這一點,並在WMIProvierHost使用了50%的CPU的整套方法(我知道這是不是一個正常用例調用WMI對象1000次)。

但是這兩個調用之間的時間差距真的幾乎沒有,這一切都歸結爲可讀性,我總是使用Process.GetProcess來查詢WMI的進程。

0

使用任何更簡單,更清潔。將來您可能需要擴展功能,並且您的項目可能會增長。初始步驟的簡單性將在以後得到回報。 WMI旨在盡一切可能,但帶來更多的開銷。對於大多數情況下,Diagnostics已經足夠好了。

時間考慮可以發揮作用,但我不認爲你想要不斷探究過程,所以這應該不是很重要。儘管如此,這方面也指向Diagnostics

更新

獲得CPU負載,可以使用PerformanceCounter類從Diagnostics命名空間。

+0

在我沒有試圖獲得「CPU負載」之前,我認爲Ststem。診斷更簡單,更清潔。現在我將使用WMI。 – Seva

+0

@Seva:我已經更新瞭如何在診斷程序中正確獲取CPU負載的答案。 –

相關問題