What I want to achieve is I can get every CPUs utilization (I have 4 CPU core, so I expect I can get all of them like in resmon.exe) and the sum of them (Like in the TaskManager.exe)
I have read on some soure on how I can get the processors utilization is by doing some math on the CPU time. I tried to use NtQuerySystemInformation to get the necessary data.
#include <windows.h>
#include <vector>
#include <iostream>
#include <winternl.h>
#pragma comment(lib, "Ntdll.lib")
typedef struct
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER DpcTime;
LARGE_INTEGER InterruptTime;
ULONG InterruptCount;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R;
static long long toInteger(LARGE_INTEGER const & integer)
{
#ifdef INT64_MAX // Does the compiler natively support 64-bit integers?
return integer.QuadPart;
#else
return (static_cast<long long>(integer.HighPart) << 32) | integer.LowPart;
#endif
}
class CPU
{
public:
uint64_t prev_idle = 0;
uint64_t prev_ker = 0;
uint64_t prev_user = 0;
uint64_t cur_idle = 0;
uint64_t cur_ker = 0;
uint64_t cur_user = 0;
double get()
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R *a = new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R[4];
// 4 is the total of CPU (4 cores)
NtQuerySystemInformation(SystemProcessorPerformanceInformation, a, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R) * 4, NULL);
prev_idle = cur_idle;
prev_ker = cur_ker;
prev_user = cur_user;
cur_idle = 0;
cur_ker = 0;
cur_user = 0;
// 4 is the total of CPU (4 cores)
// Sum up the SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R array so I can get the utilization from all of the CPU
for (int i = 0; i < 4; ++i)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R b = a[i];
cur_idle += toInteger(b.IdleTime);
cur_ker += toInteger(b.KernelTime);
cur_user += toInteger(b.UserTime);
}
std::cout << "Cur idle " << cur_idle << '\n';
std::cout << "Cur ker " << cur_ker << '\n';
std::cout << "Cur user " << cur_user << '\n';
uint64_t delta_idle = cur_idle - prev_idle;
uint64_t delta_kernel = cur_ker - prev_ker;
uint64_t delta_user = cur_user - prev_user;
std::cout << "Delta idle " << delta_idle << '\n';
std::cout << "Delta ker " << delta_kernel << '\n';
std::cout << "Delta user " << delta_user << '\n';
uint64_t total_sys = delta_kernel + delta_user;
uint64_t kernel_total = delta_kernel - delta_idle;
delete[] a;
// return (total_sys - delta_idle) * 100.0 / total_sys;
return (kernel_total + delta_user) * 100.0 / total_sys;
}
};
int main()
{
CPU a;
std::cout << "starting" << '\n';
while(1)
{
std::cout << a.get() << '\n';
Sleep(1000);
}
return 0;
}
And to get the individual CPU utilization, I don't have to sum all of the CPUs, just choose one of the SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION_R array element.
My question is
- Am I doing it right? Because when I check my program with the CPU utilization in the TaskManager.exe, it somewhat different.
- Is there any better approach other than using
NtQuerySystemInformation(Because Microsoft has mention "NtQuerySystemInformation may be altered or unavailable in future versions of Windows. Applications should use the alternate functions listed in this topic.")?

