@@ -9,7 +9,7 @@ std::wstring kProcessorFrequency =
99 L" \\ Processor Information(_Total)\\ Processor Frequency" ;
1010std::wstring kProcessorPerformance =
1111 L" \\ Processor Information(_Total)\\ % Processor Performance" ;
12- std::wstring kProcessorTime = L" \\ Processor(_Total)\\ % Processor Time" ;
12+ std::wstring kProcessorIdleTime = L" \\ Processor(_Total)\\ % Idle Time" ;
1313
1414WmiCpu::WmiCpu () {
1515 HQUERY temp_query = nullptr ;
@@ -119,13 +119,24 @@ bool WmiCpu::Sample() noexcept {
119119 }
120120 }
121121
122- // Sample cpu utilization
122+ // Sample cpu idle time, and compute cpu utilization using it (Windows 11 Fix)
123+ //
124+ // Beginning with Windows 11 22H2, the performance counters for CPU idle time
125+ // in SystemProcessorPerformanceInformation are broken and statistics derived
126+ // from those counters will always indicate single-digit cpu utilization %.
127+ //
128+ // Idle time reported in SystemProcessorIdleInformation is still consistent on
129+ // all versions of Windows, as well as WMI provisioned "Processor\% Idle Time".
130+ //
131+ // To measure CPU utilization accurately on all systems, it must be calculated:
132+ //
133+ // 100.0 - "Processor(_Total)\% Idle Time"
123134 {
124135 if (const auto result =
125- PdhGetFormattedCounterValue (processor_time_counter_ , PDH_FMT_DOUBLE,
136+ PdhGetFormattedCounterValue (processor_idle_time_counter_ , PDH_FMT_DOUBLE,
126137 &counter_type, &counter_value);
127138 result == ERROR_SUCCESS) {
128- info.cpu_utilization = counter_value.doubleValue ;
139+ info.cpu_utilization = 100.0 - counter_value.doubleValue ;
129140 SetTelemetryCapBit (CpuTelemetryCapBits::cpu_utilization);
130141 }
131142 }
0 commit comments