2015-10-28 162 views
12

我需要在執行進程期間獲取RAM內存和CPU使用情況(該進程有時可以運行超過30分鐘)。我能夠獲得可用的RAM,但CPU使用率不正確,與任務管理器的值相比較。難道我做錯了什麼?這裏是我的代碼:獲取CPU和RAM的使用情況

class Program 
{ 
    static List<float> AvailableCPU = new List<float>(); 
    static List<float> AvailableRAM = new List<float>(); 

    protected static PerformanceCounter cpuCounter; 
    protected static PerformanceCounter ramCounter; 
    static void Main(string[] args) 
    { 
     cpuCounter = new PerformanceCounter(); 
     cpuCounter.CategoryName = "Processor"; 
     cpuCounter.CounterName = "% Processor Time"; 
     cpuCounter.InstanceName = "_Total"; 

     ramCounter = new PerformanceCounter("Memory", "Available MBytes"); 

     try 
     { 
      System.Timers.Timer t = new System.Timers.Timer(1200); 
      t.Elapsed += new ElapsedEventHandler(TimerElapsed); 
      t.Start(); 
      Thread.Sleep(10000); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("catched exception"); 
     } 
     Console.ReadLine(); 

    } 

    public static void TimerElapsed(object source, ElapsedEventArgs e) 
    { 
     float cpu = cpuCounter.NextValue(); 
     float ram = ramCounter.NextValue(); 
     Console.WriteLine(string.Format("CPU Value: {0}, ram value: {1}", cpu, ram)); 
     AvailableCPU.Add(cpu); 
     AvailableRAM.Add(ram); 
    } 

} 

但是當我運行該程序,這裏是它的打印到控制檯,從任務管理器的值進行比較: cpu usage

我在做什麼錯?

+0

它在顯示屏上波動 - 也許你正在比較不同的時間範圍?你在這裏有一個2.7的值... –

+0

我已經添加了一個方法來模擬cpu的負載,並且這個值甚至與任務管理器中的值沒有接近。我每秒讀一次數值。我懷疑這可能是由於多核心CPU,但我還不確定... –

回答

6

沒有什麼錯你的價值觀。

你看到什麼任務管理器的回報差異的原因是,「CPU使用率」價值的東西對於一個給定的時間間隔計算,即,兩個NextValue()調用之間。如果任務管理器「不調用它自己的NextValue」(如果我們簡化它的工作原理),那麼您將不會返回相同的結果。

試想以下情形:

Time 0: 0% actual CPU usage 
Time 1: 50% actual CPU usage 
Time 2: 70% actual CPU usage 
Time 3: 2% actual CPU usage 
Time 4: 100% actual CPU usage 
  • 如果檢查時間1和時間3之間的值,你會返回基於 「50%和2%」 的東西。
  • 如果任務管理器檢查時間2和時間4之間的值,它將返回不同的值,即基於「70%和100%」的值。

你可以嘗試產生你自己的應用程序的多個進程,你也應該看到不同的結果。

5

這裏是我發現:我創建了一個清單,PerformanceCounter對象爲每個核心,我加的百分比和物理性核心數量劃分結果:

class Program 
    { 
     static List<float> AvailableCPU = new List<float>(); 
     static List<float> AvailableRAM = new List<float>(); 

     protected static PerformanceCounter cpuCounter; 
     protected static PerformanceCounter ramCounter; 
     static List<PerformanceCounter> cpuCounters = new List<PerformanceCounter>(); 
     static int cores = 0; 
     static void Main(string[] args) 
     { 
      cpuCounter = new PerformanceCounter(); 
      cpuCounter.CategoryName = "Processor"; 
      cpuCounter.CounterName = "% Processor Time"; 
      cpuCounter.InstanceName = "_Total"; 

      foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get()) 
      { 
       cores = cores + int.Parse(item["NumberOfCores"].ToString()); 
      } 

      ramCounter = new PerformanceCounter("Memory", "Available MBytes"); 

      int procCount = System.Environment.ProcessorCount; 
      for(int i = 0; i < procCount; i++) 
      { 
       System.Diagnostics.PerformanceCounter pc = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", i.ToString()); 
       cpuCounters.Add(pc); 
      } 

      Thread c = new Thread(ConsumeCPU); 
      c.IsBackground = true; 
      c.Start(); 

      try 
      { 
       System.Timers.Timer t = new System.Timers.Timer(1200); 
       t.Elapsed += new ElapsedEventHandler(TimerElapsed); 
       t.Start(); 
       Thread.Sleep(10000); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("catched exception"); 
      } 
      Console.ReadLine(); 

     } 

     public static void ConsumeCPU() 
     { 
      int percentage = 60; 
      if (percentage < 0 || percentage > 100) 
       throw new ArgumentException("percentage"); 
      Stopwatch watch = new Stopwatch(); 
      watch.Start(); 
      while (true) 
      { 
       // Make the loop go on for "percentage" milliseconds then sleep the 
       // remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms 
       if (watch.ElapsedMilliseconds > percentage) 
       { 
        Thread.Sleep(100 - percentage); 
        watch.Reset(); 
        watch.Start(); 
       } 
      } 
     } 

     public static void TimerElapsed(object source, ElapsedEventArgs e) 
     { 
      float cpu = cpuCounter.NextValue(); 
      float sum = 0; 
      foreach(PerformanceCounter c in cpuCounters) 
      { 
       sum = sum + c.NextValue(); 
      } 
      sum = sum/(cores); 
      float ram = ramCounter.NextValue(); 
      Console.WriteLine(string.Format("CPU Value 1: {0}, cpu value 2: {1} ,ram value: {2}", sum, cpu, ram)); 
      AvailableCPU.Add(sum); 
      AvailableRAM.Add(ram); 
     } 

    } 

下面是截圖的結果(因爲你可以看到,第一種方法更精確):

enter image description here

相關問題