Hardware/CPU/CPULoad.cs
author moel.mich
Sun, 10 Apr 2011 23:36:07 +0000
changeset 268 844ba72c11de
parent 182 4801e9eaf979
child 313 596df85bb4e1
permissions -rw-r--r--
Replaced the StreamReader based lm-sensors access with an implementation using the FileStream class in order to avoid buffering problems when seeking.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Runtime.InteropServices;
    40 
    41 namespace OpenHardwareMonitor.Hardware.CPU {
    42   internal class CPULoad {
    43 
    44     [StructLayout(LayoutKind.Sequential)]
    45     protected struct SystemProcessorPerformanceInformation {
    46       public long IdleTime;
    47       public long KernelTime;
    48       public long UserTime;
    49       public long Reserved0;
    50       public long Reserved1;
    51       public ulong Reserved2;
    52     }
    53 
    54     protected enum SystemInformationClass {
    55       SystemBasicInformation = 0,
    56       SystemCpuInformation = 1,
    57       SystemPerformanceInformation = 2,
    58       SystemTimeOfDayInformation = 3,
    59       SystemProcessInformation = 5,
    60       SystemProcessorPerformanceInformation = 8
    61     }
    62 
    63     private readonly CPUID[][] cpuid;
    64 
    65     private long systemTime;
    66     private long[] idleTimes;
    67 
    68     private float totalLoad;
    69     private readonly float[] coreLoads;
    70 
    71     private readonly bool available;
    72 
    73     private static long[] GetIdleTimes() {      
    74       SystemProcessorPerformanceInformation[] informations = new
    75         SystemProcessorPerformanceInformation[64];
    76 
    77       int size = Marshal.SizeOf(typeof(SystemProcessorPerformanceInformation));
    78 
    79       IntPtr returnLength;
    80       if (NativeMethods.NtQuerySystemInformation(
    81         SystemInformationClass.SystemProcessorPerformanceInformation,
    82         informations, informations.Length * size, out returnLength) != 0)
    83         return null;
    84 
    85       long[] result = new long[(int)returnLength / size];
    86 
    87       for (int i = 0; i < result.Length; i++)
    88         result[i] = informations[i].IdleTime;
    89 
    90       return result;
    91     }
    92 
    93     public CPULoad(CPUID[][] cpuid) {
    94       this.cpuid = cpuid;
    95       this.coreLoads = new float[cpuid.Length];         
    96       this.systemTime = DateTime.Now.Ticks;
    97       this.totalLoad = 0;
    98       try {
    99         this.idleTimes = GetIdleTimes();
   100       } catch (Exception) {
   101         this.idleTimes = null;
   102       }
   103       if (idleTimes != null)
   104         available = true;
   105     }
   106 
   107     public bool IsAvailable {
   108       get { return available; }
   109     }
   110 
   111     public float GetTotalLoad() {
   112       return totalLoad;
   113     }
   114 
   115     public float GetCoreLoad(int core) {
   116       return coreLoads[core];
   117     }
   118 
   119     public void Update() {
   120       if (this.idleTimes == null)
   121         return;
   122 
   123       long newSystemTime = DateTime.Now.Ticks;
   124       long[] newIdleTimes = GetIdleTimes();
   125 
   126       if (newSystemTime - this.systemTime < 10000)
   127         return;
   128 
   129       if (newIdleTimes == null)
   130         return;
   131 
   132       float total = 0;
   133       int count = 0;
   134       for (int i = 0; i < cpuid.Length; i++) {
   135         float value = 0;
   136         for (int j = 0; j < cpuid[i].Length; j++) {
   137           long index = cpuid[i][j].Thread;
   138           if (index < newIdleTimes.Length) {
   139             long delta = newIdleTimes[index] - this.idleTimes[index];
   140             value += delta;
   141             total += delta;
   142             count++;
   143           }
   144         }
   145         value = 1.0f - value / (cpuid[i].Length * 
   146           (newSystemTime - this.systemTime));
   147         value = value < 0 ? 0 : value;
   148         coreLoads[i] = value * 100;
   149       }
   150       if (count > 0) {
   151         total = 1.0f - total / (count * (newSystemTime - this.systemTime));
   152         total = total < 0 ? 0 : total;
   153       } else {
   154         total = 0;
   155       }
   156       this.totalLoad = total * 100;
   157 
   158       this.systemTime = newSystemTime;
   159       this.idleTimes = newIdleTimes;
   160     }
   161 
   162     protected static class NativeMethods {
   163 
   164       [DllImport("ntdll.dll")]
   165       public static extern int NtQuerySystemInformation(
   166         SystemInformationClass informationClass,
   167         [Out] SystemProcessorPerformanceInformation[] informations,
   168         int structSize, out IntPtr returnLength);
   169     }
   170   }
   171 }