Hardware/CPU/CPULoad.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 195 0ee888c485d5
child 344 3145aadca3d2
permissions -rw-r--r--
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
moel@26
     1
/*
moel@26
     2
  
moel@26
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@26
     4
moel@26
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@26
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@26
     7
  the License. You may obtain a copy of the License at
moel@26
     8
 
moel@26
     9
  http://www.mozilla.org/MPL/
moel@26
    10
moel@26
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@26
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@26
    13
  for the specific language governing rights and limitations under the License.
moel@26
    14
moel@26
    15
  The Original Code is the Open Hardware Monitor code.
moel@26
    16
moel@26
    17
  The Initial Developer of the Original Code is 
moel@26
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@313
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@26
    20
  the Initial Developer. All Rights Reserved.
moel@26
    21
moel@26
    22
  Contributor(s):
moel@26
    23
moel@26
    24
  Alternatively, the contents of this file may be used under the terms of
moel@26
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@26
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@26
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@26
    28
  of those above. If you wish to allow use of your version of this file only
moel@26
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@26
    30
  use your version of this file under the terms of the MPL, indicate your
moel@26
    31
  decision by deleting the provisions above and replace them with the notice
moel@26
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@26
    33
  the provisions above, a recipient may use your version of this file under
moel@26
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@26
    35
 
moel@26
    36
*/
moel@26
    37
moel@26
    38
using System;
moel@26
    39
using System.Runtime.InteropServices;
moel@26
    40
moel@26
    41
namespace OpenHardwareMonitor.Hardware.CPU {
moel@165
    42
  internal class CPULoad {
moel@26
    43
moel@26
    44
    [StructLayout(LayoutKind.Sequential)]
moel@195
    45
    protected struct SystemProcessorPerformanceInformation {
moel@26
    46
      public long IdleTime;
moel@26
    47
      public long KernelTime;
moel@26
    48
      public long UserTime;
moel@26
    49
      public long Reserved0;
moel@26
    50
      public long Reserved1;
moel@26
    51
      public ulong Reserved2;
moel@26
    52
    }
moel@26
    53
moel@195
    54
    protected enum SystemInformationClass {
moel@26
    55
      SystemBasicInformation = 0,
moel@26
    56
      SystemCpuInformation = 1,
moel@26
    57
      SystemPerformanceInformation = 2,
moel@26
    58
      SystemTimeOfDayInformation = 3,
moel@26
    59
      SystemProcessInformation = 5,
moel@26
    60
      SystemProcessorPerformanceInformation = 8
moel@26
    61
    }
moel@26
    62
moel@195
    63
    private readonly CPUID[][] cpuid;
moel@26
    64
moel@26
    65
    private long[] idleTimes;
moel@313
    66
    private long[] totalTimes;
moel@26
    67
moel@26
    68
    private float totalLoad;
moel@195
    69
    private readonly float[] coreLoads;
moel@26
    70
moel@195
    71
    private readonly bool available;
moel@26
    72
moel@313
    73
    private static bool GetTimes(out long[] idle, out long[] total) {      
moel@26
    74
      SystemProcessorPerformanceInformation[] informations = new
moel@99
    75
        SystemProcessorPerformanceInformation[64];
moel@99
    76
moel@99
    77
      int size = Marshal.SizeOf(typeof(SystemProcessorPerformanceInformation));
moel@26
    78
moel@313
    79
      idle = null;
moel@313
    80
      total = null;
moel@313
    81
moel@26
    82
      IntPtr returnLength;
moel@167
    83
      if (NativeMethods.NtQuerySystemInformation(
moel@26
    84
        SystemInformationClass.SystemProcessorPerformanceInformation,
moel@167
    85
        informations, informations.Length * size, out returnLength) != 0)
moel@313
    86
        return false;
moel@99
    87
moel@313
    88
      idle = new long[(int)returnLength / size];
moel@313
    89
      total = new long[(int)returnLength / size];
moel@26
    90
moel@313
    91
      for (int i = 0; i < idle.Length; i++) {
moel@313
    92
        idle[i] = informations[i].IdleTime;
moel@313
    93
        total[i] = informations[i].KernelTime + informations[i].UserTime;
moel@313
    94
      }
moel@26
    95
moel@313
    96
      return true;
moel@26
    97
    }
moel@26
    98
moel@90
    99
    public CPULoad(CPUID[][] cpuid) {
moel@90
   100
      this.cpuid = cpuid;
moel@90
   101
      this.coreLoads = new float[cpuid.Length];         
moel@26
   102
      this.totalLoad = 0;
moel@26
   103
      try {
moel@313
   104
        GetTimes(out idleTimes, out totalTimes);
moel@26
   105
      } catch (Exception) {
moel@26
   106
        this.idleTimes = null;
moel@313
   107
        this.totalTimes = null;
moel@26
   108
      }
moel@26
   109
      if (idleTimes != null)
moel@26
   110
        available = true;
moel@26
   111
    }
moel@26
   112
moel@26
   113
    public bool IsAvailable {
moel@26
   114
      get { return available; }
moel@26
   115
    }
moel@26
   116
moel@26
   117
    public float GetTotalLoad() {
moel@26
   118
      return totalLoad;
moel@26
   119
    }
moel@26
   120
moel@26
   121
    public float GetCoreLoad(int core) {
moel@26
   122
      return coreLoads[core];
moel@26
   123
    }
moel@26
   124
moel@26
   125
    public void Update() {
moel@26
   126
      if (this.idleTimes == null)
moel@26
   127
        return;
moel@26
   128
moel@313
   129
      long[] newIdleTimes;
moel@313
   130
      long[] newTotalTimes;
moel@26
   131
moel@313
   132
      if (!GetTimes(out newIdleTimes, out newTotalTimes))
moel@167
   133
        return;
moel@167
   134
moel@313
   135
      for (int i = 0; i < Math.Min(newTotalTimes.Length, totalTimes.Length); i++) 
moel@313
   136
        if (newTotalTimes[i] - this.totalTimes[i] < 100000)
moel@313
   137
          return;
moel@313
   138
moel@313
   139
      if (newIdleTimes == null || newTotalTimes == null)
moel@26
   140
        return;
moel@26
   141
moel@26
   142
      float total = 0;
moel@90
   143
      int count = 0;
moel@90
   144
      for (int i = 0; i < cpuid.Length; i++) {
moel@26
   145
        float value = 0;
moel@90
   146
        for (int j = 0; j < cpuid[i].Length; j++) {
moel@90
   147
          long index = cpuid[i][j].Thread;
moel@313
   148
          if (index < newIdleTimes.Length && index < totalTimes.Length) {
moel@313
   149
            float idle = 
moel@313
   150
              (float)(newIdleTimes[index] - this.idleTimes[index]) /
moel@313
   151
              (float)(newTotalTimes[index] - this.totalTimes[index]);
moel@313
   152
            value += idle;
moel@313
   153
            total += idle;
moel@99
   154
            count++;
moel@99
   155
          }
moel@26
   156
        }
moel@313
   157
        value = 1.0f - value / cpuid[i].Length;
moel@26
   158
        value = value < 0 ? 0 : value;
moel@26
   159
        coreLoads[i] = value * 100;
moel@26
   160
      }
moel@99
   161
      if (count > 0) {
moel@313
   162
        total = 1.0f - total / count;
moel@99
   163
        total = total < 0 ? 0 : total;
moel@99
   164
      } else {
moel@99
   165
        total = 0;
moel@99
   166
      }
moel@26
   167
      this.totalLoad = total * 100;
moel@26
   168
moel@313
   169
      this.totalTimes = newTotalTimes;
moel@167
   170
      this.idleTimes = newIdleTimes;
moel@26
   171
    }
moel@26
   172
moel@195
   173
    protected static class NativeMethods {
moel@167
   174
moel@167
   175
      [DllImport("ntdll.dll")]
moel@167
   176
      public static extern int NtQuerySystemInformation(
moel@167
   177
        SystemInformationClass informationClass,
moel@167
   178
        [Out] SystemProcessorPerformanceInformation[] informations,
moel@167
   179
        int structSize, out IntPtr returnLength);
moel@167
   180
    }
moel@26
   181
  }
moel@26
   182
}