diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetCpuUtilization.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetCpuUtilization.cs index da8fca2c75d9a7..244aa3a903152a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetCpuUtilization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetCpuUtilization.cs @@ -16,6 +16,6 @@ internal struct ProcessCpuInformation } [LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetCpuUtilization")] - internal static partial int GetCpuUtilization(ref ProcessCpuInformation previousCpuInfo); + internal static partial double GetCpuUtilization(ref ProcessCpuInformation previousCpuInfo); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 5340fe8de8325a..e358c49f15028a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -88,7 +88,7 @@ protected override void OnEventCommand(EventCommandEventArgs command) // overhead by at all times even when counters aren't enabled. // On disable, PollingCounters will stop polling for values so it should be fine to leave them around. - _cpuTimeCounter ??= new PollingCounter("cpu-usage", this, () => RuntimeEventSourceHelper.GetCpuUsage()) { DisplayName = "CPU Usage", DisplayUnits = "%" }; + _cpuTimeCounter ??= new PollingCounter("cpu-usage", this, RuntimeEventSourceHelper.GetCpuUsage) { DisplayName = "CPU Usage", DisplayUnits = "%" }; _workingSetCounter ??= new PollingCounter("working-set", this, () => ((double)Environment.WorkingSet / 1_000_000)) { DisplayName = "Working Set", DisplayUnits = "MB" }; _gcHeapSizeCounter ??= new PollingCounter("gc-heap-size", this, () => ((double)GC.GetTotalMemory(false) / 1_000_000)) { DisplayName = "GC Heap Size", DisplayUnits = "MB" }; _gen0GCCounter ??= new IncrementingPollingCounter("gen-0-gc-count", this, () => GC.CollectionCount(0)) { DisplayName = "Gen 0 GC Count", DisplayRateTimeScale = new TimeSpan(0, 1, 0) }; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Unix.cs index abc5ddd19477d1..fd58b336a4395b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Unix.cs @@ -7,7 +7,7 @@ internal static class RuntimeEventSourceHelper { private static Interop.Sys.ProcessCpuInformation s_cpuInfo; - internal static int GetCpuUsage() => + internal static double GetCpuUsage() => Interop.Sys.GetCpuUtilization(ref s_cpuInfo) / Environment.ProcessorCount; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Windows.cs index 7dc8b40e0a99ad..8c797c7f9fcea3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSourceHelper.Windows.cs @@ -10,11 +10,11 @@ internal static class RuntimeEventSourceHelper private static long s_prevSystemUserTime; private static long s_prevSystemKernelTime; - internal static int GetCpuUsage() + internal static double GetCpuUsage() { // Returns the current process' CPU usage as a percentage - int cpuUsage = 0; + double cpuUsage = 0.0; if (Interop.Kernel32.GetProcessTimes(Interop.Kernel32.GetCurrentProcess(), out _, out _, out long procKernelTime, out long procUserTime) && Interop.Kernel32.GetSystemTimes(out _, out long systemUserTime, out long systemKernelTime)) @@ -25,7 +25,7 @@ internal static int GetCpuUsage() if (s_prevSystemUserTime != 0 && s_prevSystemKernelTime != 0 && // These may be 0 when we report CPU usage for the first time, in which case we should just return 0. totalSystemTime != 0) { - cpuUsage = (int)(totalProcTime * 100 / totalSystemTime); + cpuUsage = (totalProcTime * 100.0 / totalSystemTime); } s_prevProcUserTime = procUserTime; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs index fe1eaa37d7577b..ea754f9185e9bf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.CpuUtilizationReader.Unix.cs @@ -9,7 +9,7 @@ private struct CpuUtilizationReader { private Interop.Sys.ProcessCpuInformation _cpuInfo; - public int CurrentUtilization => + public double CurrentUtilization => Interop.Sys.GetCpuUtilization(ref _cpuInfo) / Environment.ProcessorCount; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.GateThread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.GateThread.cs index 2843f99347ca50..26512a4e81c636 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.GateThread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.GateThread.cs @@ -102,7 +102,7 @@ private static void GateThreadStart() (uint)threadPoolInstance.GetAndResetHighWatermarkCountOfThreadsProcessingUserCallbacks()); } - int cpuUtilization = cpuUtilizationReader.CurrentUtilization; + int cpuUtilization = (int)cpuUtilizationReader.CurrentUtilization; threadPoolInstance._cpuUtilization = cpuUtilization; bool needGateThreadForRuntime = ThreadPool.PerformRuntimeSpecificGateActivities(cpuUtilization); diff --git a/src/native/libs/System.Native/pal_time.c b/src/native/libs/System.Native/pal_time.c index cffe378a83cbac..588277afdf5925 100644 --- a/src/native/libs/System.Native/pal_time.c +++ b/src/native/libs/System.Native/pal_time.c @@ -95,7 +95,7 @@ uint64_t SystemNative_GetTimestamp() #endif } -int32_t SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo) +double SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo) { uint64_t kernelTime = 0; uint64_t userTime = 0; @@ -109,7 +109,7 @@ int32_t SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo) else { kernelTime = - ((uint64_t)(resUsage.ru_stime.tv_sec) * SecondsToNanoSeconds) + + ((uint64_t)(resUsage.ru_stime.tv_sec) * SecondsToNanoSeconds) + ((uint64_t)(resUsage.ru_stime.tv_usec) * MicroSecondsToNanoSeconds); userTime = ((uint64_t)(resUsage.ru_utime.tv_sec) * SecondsToNanoSeconds) + @@ -134,10 +134,10 @@ int32_t SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo) cpuBusyTime = (userTime - lastRecordedUserTime) + (kernelTime - lastRecordedKernelTime); } - int32_t cpuUtilization = 0; + double cpuUtilization = 0.0; if (cpuTotalTime > 0 && cpuBusyTime > 0) { - cpuUtilization = (int32_t)(cpuBusyTime * 100 / cpuTotalTime); + cpuUtilization = ((double)cpuBusyTime * 100.0 / (double)cpuTotalTime); } previousCpuInfo->lastRecordedCurrentTime = currentTime; diff --git a/src/native/libs/System.Native/pal_time.h b/src/native/libs/System.Native/pal_time.h index c7ef77da1e5bd5..8660902f4761f5 100644 --- a/src/native/libs/System.Native/pal_time.h +++ b/src/native/libs/System.Native/pal_time.h @@ -48,4 +48,4 @@ PALEXPORT uint64_t SystemNative_GetTimestamp(void); * returned is sum of utilization across all processors, e.g. this function will * return 200 when two cores are running at 100%. */ -PALEXPORT int32_t SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo); +PALEXPORT double SystemNative_GetCpuUtilization(ProcessCpuInformation* previousCpuInfo);