From d901c079b7b6c163f808d4e5aaa994cf653a8e2b Mon Sep 17 00:00:00 2001 From: asrulhadi Date: Thu, 16 Mar 2023 17:28:47 +0800 Subject: [PATCH] Linux cpu load (#981) --- .../Hardware/Cpu/CpuLoad.cs | 81 ++++++++++++++++--- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs b/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs index ceff770..e693041 100644 --- a/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs +++ b/LibreHardwareMonitorLib/Hardware/Cpu/CpuLoad.cs @@ -5,6 +5,8 @@ // All Rights Reserved. using System; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -12,8 +14,9 @@ namespace LibreHardwareMonitor.Hardware.CPU; internal class CpuLoad { - private long[] _idleTimes; private readonly float[] _threadLoads; + + private long[] _idleTimes; private float _totalLoad; private long[] _totalTimes; @@ -21,6 +24,7 @@ internal class CpuLoad { _threadLoads = new float[cpuid.Sum(x => x.Length)]; _totalLoad = 0; + try { GetTimes(out _idleTimes, out _totalTimes); @@ -38,6 +42,11 @@ internal class CpuLoad public bool IsAvailable { get; } private static bool GetTimes(out long[] idle, out long[] total) + { + return !Software.OperatingSystem.IsUnix ? GetWindowsTimes(out idle, out total) : GetUnixTimes(out idle, out total); + } + + private static bool GetWindowsTimes(out long[] idle, out long[] total) { idle = null; total = null; @@ -46,30 +55,80 @@ internal class CpuLoad Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[] idleInformation = new Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION[64]; int idleSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_IDLE_INFORMATION)); if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorIdleInformation, idleInformation, idleInformation.Length * idleSize, out int idleReturn) != 0) - { return false; - } //Query processor performance information Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[] perfInformation = new Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[64]; int perfSize = Marshal.SizeOf(typeof(Interop.NtDll.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, perfInformation, perfInformation.Length * perfSize, out int perfReturn) != 0) + if (Interop.NtDll.NtQuerySystemInformation(Interop.NtDll.SYSTEM_INFORMATION_CLASS.SystemProcessorPerformanceInformation, + perfInformation, + perfInformation.Length * perfSize, + out int perfReturn) != 0) { return false; } idle = new long[idleReturn / idleSize]; for (int i = 0; i < idle.Length; i++) - { idle[i] = idleInformation[i].IdleTime; - } total = new long[perfReturn / perfSize]; for (int i = 0; i < total.Length; i++) - { total[i] = perfInformation[i].KernelTime + perfInformation[i].UserTime; + + return true; + } + + private static bool GetUnixTimes(out long[] idle, out long[] total) + { + idle = null; + total = null; + + List idleList = new(); + List totalList = new(); + + if (!File.Exists("/proc/stat")) + return false; + + string[] cpuInfos = File.ReadAllLines("/proc/stat"); + + // currently parse the OverAll CPU info + // cpu 1583083 737 452845 36226266 723316 63685 31896 0 0 0 + // cpu0 397468 189 109728 9040007 191429 16939 14954 0 0 0 + // 0=cpu 1=user 2=nice 3=system 4=idle 5=iowait 6=irq 7=softirq 8=steal 9=guest 10=guest_nice + foreach (string cpuInfo in cpuInfos.Where(s => s.StartsWith("cpu") && s.Length > 3 && s[3] != ' ')) + { + string[] overall = cpuInfo.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + + try + { + // Parse idle information. + idleList.Add(long.Parse(overall[4])); + } + catch + { + // Ignored. + } + + // Parse total information = user + nice + system + idle + iowait + irq + softirq + steal + guest + guest_nice. + long currentTotal = 0; + foreach (string item in overall.Skip(1)) + { + try + { + currentTotal += long.Parse(item); + } + catch + { + // Ignored. + } + } + + totalList.Add(currentTotal); } + idle = idleList.ToArray(); + total = totalList.ToArray(); return true; } @@ -85,15 +144,13 @@ internal class CpuLoad public void Update() { - if (_idleTimes == null) - return; - - if (!GetTimes(out long[] newIdleTimes, out long[] newTotalTimes)) + if (_idleTimes == null || !GetTimes(out long[] newIdleTimes, out long[] newTotalTimes)) return; + int minDiff = Software.OperatingSystem.IsUnix ? 100 : 100000; for (int i = 0; i < Math.Min(newTotalTimes.Length, _totalTimes.Length); i++) { - if (newTotalTimes[i] - _totalTimes[i] < 100000) + if (newTotalTimes[i] - _totalTimes[i] < minDiff) return; }