| 74 | |
| 75 | |
| 76 | CpuTelemetryInfo WmiCpu::Sample() noexcept { |
| 77 | DWORD counter_type; |
| 78 | |
| 79 | LARGE_INTEGER qpc; |
| 80 | QueryPerformanceCounter(&qpc); |
| 81 | const bool should_collect = qpc.QuadPart >= next_sample_qpc_.QuadPart; |
| 82 | |
| 83 | CpuTelemetryInfo info{ |
| 84 | .qpc = (uint64_t)qpc.QuadPart, |
| 85 | }; |
| 86 | |
| 87 | if (should_collect) { |
| 88 | if (const auto result = PdhCollectQueryData(query_.get()); |
| 89 | result != ERROR_SUCCESS) { |
| 90 | LOG(INFO) << "PdhCollectQueryData failed. Result:" << result << std::endl; |
| 91 | } else { |
| 92 | // Update the next sample qpc based on the current sample qpc |
| 93 | // and adding in the frequency |
| 94 | next_sample_qpc_.QuadPart = qpc.QuadPart + frequency_.QuadPart; |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Sample cpu clock. This is an approximation using the frequency and then |
| 99 | // the current percentage. |
| 100 | PDH_FMT_COUNTERVALUE counter_value; |
| 101 | { |
| 102 | if (const auto result = PdhGetFormattedCounterValue( |
| 103 | processor_frequency_counter_, PDH_FMT_DOUBLE, &counter_type, |
| 104 | &counter_value); |
| 105 | result == ERROR_SUCCESS) { |
| 106 | info.cpu_frequency = counter_value.doubleValue; |
| 107 | |
| 108 | if (const auto result2 = PdhGetFormattedCounterValue( |
| 109 | processor_performance_counter_, PDH_FMT_DOUBLE, &counter_type, |
| 110 | &counter_value); |
| 111 | result2 == ERROR_SUCCESS) { |
| 112 | info.cpu_frequency = |
| 113 | info.cpu_frequency * (counter_value.doubleValue / 100.); |
| 114 | SetTelemetryCapBit(CpuTelemetryCapBits::cpu_frequency); |
| 115 | } |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | // Sample cpu idle time, and compute cpu utilization using it (Windows 11 Fix) |
| 120 | // |
| 121 | // Beginning with Windows 11 22H2, the performance counters for CPU idle time |
| 122 | // in SystemProcessorPerformanceInformation are broken and statistics derived |
| 123 | // from those counters will always indicate single-digit cpu utilization %. |
| 124 | // |
| 125 | // Idle time reported in SystemProcessorIdleInformation is still consistent on |
| 126 | // all versions of Windows, as well as WMI provisioned "Processor\% Idle Time". |
| 127 | // |
| 128 | // To measure CPU utilization accurately on all systems, it must be calculated: |
| 129 | // |
| 130 | // 100.0 - "Processor(_Total)\% Idle Time" |
| 131 | { |
| 132 | if (const auto result = |
| 133 | PdhGetFormattedCounterValue(processor_idle_time_counter_, PDH_FMT_DOUBLE, |
no outgoing calls
no test coverage detected