How to get TaskManager process CPU usage programmatically

Recently I had a chance to realize that PerfMon "\\Process\\% Processor Time" for the single process, is actually different counter than "CPU usage", displayed in the Task Manager. Performance Counters are accessed through *PerfMon API*, header file Pdh.h:
https://docs.microsoft.com/en-us/windows/win32/api/pdh/

whereas there's no direct way to get TaskManager's CPU Usage.

Here’s a thread from Microsoft TechNet, discussing differences, unfortunately does not solve my problem:
https://social.technet.microsoft.com/Forums/en-US/0435e7c5-3cda-41a0-953e-7fa462fde03b/perfmon-process-processor-time-vs-task-manager8217s-cpu-usage-for-monitoring-a-specific?forum=perfmon


Problem emerged when I realized, how huge discrepancies between values they provide.
In my application I need to measure % CPU usage, exactly or at least very close to values, provided by the Task Manager. However, values provided by PerfMon API could be 20-30% lower, why even discrepancies are different and not proportional, is an another question. For example, if tested process payload 50-55% according to Task Manager, PerfMon API reports 35-40%

Here’s my class, implemented for calculating total process CPU usage using PerfMon API (return codes check and insignificant parts of the code have been skipped)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    // PdhCPUCounter.h

    class PdhCPUCounter {
    public:
    
        // @param counter_name: "\\Process(*ProcessName*)\\% Processor Time"
        explicit PdhCPUCounter(const std::string& counter_name);
    
        // Release handles here
        virtual ~PdhCPUCounter();
    
        // Provide actual CPU usage value in range [0.0, 1.0]
        double getCPUUtilization() const;
    
    private:
    
        // Low-level query
        PDH_FMT_COUNTERVALUE getFormattedCounterValue() const;
    
        // Needed for calculation
        size_t m_threads;
    
        // Counter format: "\\Process(*ProcessName*)\\% Processor Time"
        std::string m_counter_name;
    
        // CPU counter handle
        PDH_HCOUNTER m_counter = INVALID_HANDLE_VALUE;
    
        // Query to PerfMon handle
        PDH_HQUERY m_query = INVALID_HANDLE_VALUE;
    };

    // PdhCPUCounter.cpp

    PdhCPUCounter::PdhCPUCounter(const std::string& counter_name) : 
        m_counter_name(counter_name),
        m_threads(std::thread::hardware_concurrency())
    {
        PdhOpenQuery(nullptr, 0, &m_query);
        PdhAddEnglishCounter(m_query, m_counter_name.c_str(), 0, &m_counter);
        PdhCollectQueryData(m_query);
    }
    
    PDH_FMT_COUNTERVALUE PdhCPUCounter::getFormattedCounterValue() const
    {
        PdhCollectQueryData(m_query);
    
        PDH_FMT_COUNTERVALUE val;
        PdhGetFormattedCounterValue(m_counter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, nullptr, &val);
        return val;
    }
    
    double PdhCPUCounter::getCPUUtilization() const
    {
        const auto &val = getFormattedCounterValue();
        return val.doubleValue / m_threads;
    }

    // Usage
    // Monitor.exe is a test process here, which gives about 50-55% CPU usage in TaskManager
    processor_time = std::make_unique<PdhCPUCounter>("\\Process(Monitor)\\% Processor Time");
    // Here we're reported about 0.35 +/- 0.05
    double cpu_utilization = processor_time->getCPUUtilization();


As I found out from the TechNet thread above, Microsoft utilizes NtQuerySystemInformation for the Task Manager implementation.

However, the call

 
NtQuerySystemInformation(SystemProcessInformation, processInfo, processInfoSize, NULL);


fills out values of a structure

1
2
3
4
5
6
7
8
9
10
11
12
13
    typedef struct _SYSTEM_PROCESS_INFO
    {
        ULONG                   NextEntryOffset;
        ULONG                   NumberOfThreads;
        LARGE_INTEGER           Reserved[3];
        LARGE_INTEGER           CreateTime;
        LARGE_INTEGER           UserTime;
        LARGE_INTEGER           KernelTime;
        UNICODE_STRING          ImageName;
        ULONG                   BasePriority;
        HANDLE                  ProcessId;
        HANDLE                  InheritedFromProcessId;
    }SYSTEM_PROCESS_INFO,*PSYSTEM_PROCESS_INFO;


which also does not contain direct value for CPU utilization! Yes, it includes CreateTime, UserTime and KernelTime, however, provided these values, how to calculate CPU usage in a given period of time?
Last edited on
Is this anywhere close?
(UserTime+KernelTime)/(Now-CreateTime)*100

What is measure unit of Now in terms of UserTime/KernelTime? And how to request it?
Last edited on
Dunno, I left it as an easy exercise for you.

unfortunately I also faced such a problem
Dunno, I left it as an easy exercise for you


That's an immature explanation. There's no shame to admit you don't know or forgot it. Also, you forgot to divide value by number of available cores.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// cpu_counter.c

GetNativeSystemInfo(&systemInfo);
processorsAvailable = systemInfo.dwNumberOfProcessors;

NtQuerySystemInformation(SystemProcessInformation, processInformation, 1024 * 1024, NULL);

// ...

FILETIME currentMoment;
ZeroMemory(&currentMoment, sizeof(FILETIME));
GetSystemTimeAsFileTime(&currentMoment);
LONGLONG currentFiletime64 = (LONGLONG)(currentMoment.dwHighDateTime) << 32 | currentMoment.dwLowDateTime;

double totalTime = (double)(processInformation->KernelTime.QuadPart + processInformation->UserTime.QuadPart);
double passedTime = (double)(currentFiletime64 - processInformation->CreateTime.QuadPart);
double testPayload = totalTime / passedTime / processorsAvailable;
printf("TotalTime=%.6f; PassedTime=%.6f; Payload=%.6f\n", totalTime, passedTime, testPayload);


However, value deviation is still 3-4%, test payload process designed to occupy 48-50%, reported value 44-46%
Last edited on
Neither, I just couldn't be arsed to do any more google foo for you.

You're obviously past the hand-holding stage when it comes to programming, so asking what amounts to a STFW question got the short answer.

cpu use is not easy to get exactly, and it lags. You can only know what it was in the recent past, not what it is NOW. And the recent past value is a % over a time window, eg over the last 1 second 80% of those subsecond slices had an instruction being executed. I would not worry about a < 5% margin of error unless this is high precision super critical code. If you are doing something very exotic, you need to research, probably at the assembly language/ cpu level, a better way to get the info you need.
I just couldn't be arsed to do any more google foo for you


It means you don't know the answer, so as I.
As I said, no shame to admit it, and definitely no need to be rude - it makes you look unprofessional.
eg over the last 1 second 80% of those subsecond slices had an instruction being executed. I would not worry about a < 5% margin of error unless this is high precision super critical code


Realized it already.
Unfortunately, it's a high precision code. I found an example, it's quite complicated and need to deal with value deltas. I will post the solution as soon as I finish the implementation (or rather a link to the solution, it's not easy and compact as I said)
Last edited on
Depending on what you are doing and what hardware and more...
you probably already got to this point but
- it isnt easy to be executing an instruction that tells you if some other instruction is being executed. You are talking about looking at the CPU pipelines directly on top of guessing the branch prediction stuff.
- the cores on most CPU don't talk at this level, so its also not easy to have core#1 spying on core#2 on most normal systems. They are not wired up that way, that I know of (could be, but I have never heard of such).

that leaves me with the idea that it MAY (I hate doing that, but I honestly do not know) be possible to have core#2 looking at the voltage and or heat sensor on core#1. There are some big if's in that... if the current voltage is directly related to use being a big one, it may not be, and its not clear if core#2 can see this info.... there may also be something a level above the CPU that you can use, maybe on a bridge somewhere, but there again, I just do not know. If what you found works, that is cool too, but this sounds like something that should be fairly simple to do IF you can find a source of reliable information that gives the desired answer. I would be wary of a complicated answer, though it may work, would have to know what the approach was. An obvious problem is that if the cores are all on one chip, there may only be ONE volt and temp sensor for all of them, which means all you would get is an estimate of how many of the cores are running. The last time I played at this level, multi cores were not available in embedded systems... so I didn't have to think about that kind of stuff.
Last edited on
I wrote one of these a while ago in a different language (which seems to be a hated language to the supposedly "politically-correct" these days). It worked and it split the response automatically into different progress bars, one per each CPU core. Therefore, I know that (in general) your question can be done, as I have done it. But, and here is a conditional, as you have been told by previous posters, it might not necessarily have been exact to the microsecond CPU percentage. I had thought about that and I think that I might have a solution for you.

If you can hook and subclass the “taskmgr.exe”, then you might be able to read all Windows' messages going into it. Maybe like this in level of hooking, taskmanager/Processes/CPU. If you cannot get a windows handle on the Processes or on the CPU due to the entire taskmanager being encapsulated into one Windows' handle, then get the pre-handle process reference which is used before the process is brought into the arena of the overall handle. Kind of like subclassing Firefox's separate tabs before they are set up as part of the overall single (only one!) window's handle: it has been done, it can be done.

For accuracy at a level of what Windows shows in it's taskmanager, I would suggest hooking and subclassing as I described.

Let us know how it goes. I am interested this, but I am a beginner at C++11, for now.










atatat ! Such a great idea.

I think that your question is an interesting topic. I have been thinking that knowing CPU usage could be valuable to some ongoing programs. I have been trying to learn C++11 via writing a game and I think that I might be able to use such code.

If the game has a lot of action, decisions, etc. going on and it causes the average CPU core on the current user's computer to be above (maybe 80%) then if the CPU usage program part detected that, the main program could bypass some activities and be less likely to stall in process. Maybe (?)

I found an example, it's quite complicated and need to deal with value deltas. I will post the solution as soon as I finish the implementation (or rather a link to the solution, it's not easy and compact as I said)


If you put this into a procedure that would be nice. And, a full working example of using it. I am very new at C++, and I have been studying working examples, which seems to be a way to learn how to code correctly.

Maybe publish a "how to" which includes a zip file. And, tell us where it is.

Thanks.
Topic archived. No new replies allowed.