Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving CPU Load Percent total in Windows with C++

Tags:

I've been working on this tool to quickly log some system stats, like memory info, and cpu load percentage (like what's shown in the Task Manager). I seem to have the memory and logging part taken care of, but figuring out the CPU percentage has been very tough :( I've found a lot info on methods to check CPU info, but outside of abstracts pretty much none of the code samples I've found compile, or are well commented, so it's been hard for me to hash out a way to do this. I've already read through a lot of stackoverflow questions about getting CPU timings and such, but I haven't been able to put the pieces together.

Maybe I'm missing the point, but it seems like a popular way to figure this out is by querying the CPU two times with at least 200ms between each check to help avoid problems with something called... resolution? So yeah! How the heck do I do that? :( I'm syntactically challenged D:

I'm going to share my source code so you can see what exactly I've been up to, up until now. It's all in just one .cpp, I'm using VS2013 Express for C++, and it's only for Windows for multicore CPUs.

Warning in advance: I'm so sorry for all the comments in the code :x Also, if you copy this code and run it, it's going to generate a .CSV file called log.CSV

//included libraries/functionality for input/output #include <iostream> #include <fstream> #include <windows.h> using namespace std;  //creates a static variable to convert Bytes to Megabytes #define MB 1048576   //main program code loop int main() {     //Code block intiialization for the memory referenced in the Kernell     MEMORYSTATUSEX memStat;     memStat.dwLength = sizeof (memStat);     GlobalMemoryStatusEx(&memStat);       //loads the SYSTEMTIME     SYSTEMTIME sysTime;     //Retrieves data so that we have a way to Get it to output when using the pointers     GetSystemTime(&sysTime);       //setting the I/O for our log file to be "myfile"     ofstream myfile;     // ios::out means that we're outputting data to the file     // ios::app means that all the data we're outputting goes to the end of that log file instead of the start     myfile.open("log.csv", ios::out | ios::app);       //a while loop that gathers and logs data every quarter of a second to gather 4 data points in one second     int counter = 0;     while (counter < 4)     {         //Timestamp + Memory Info, and eventually CPU Load percentage         myfile << sysTime.wHour << ":" << sysTime.wMinute << ":" << sysTime.wMilliseconds << ", " << memStat.dwMemoryLoad << "%, " << memStat.ullTotalPhys / MB << ", " << memStat.ullAvailPhys / MB << ", " << memStat.ullTotalPageFile / MB << ", " << memStat.ullAvailPageFile / MB << ", " << memStat.ullTotalVirtual / MB << ", " << memStat.ullAvailVirtual / MB << ", " << memStat.ullAvailExtendedVirtual / MB << "\n";         //250 millisecond sleep delay          Sleep(250);         counter = counter + 1;     }         //close the log file before terminating the program         myfile.close();      return 0; //standard main() end of program terminator } 

edit#2:

I ran across this

BOOL WINAPI GetSystemTimes(_Out_opt_  LPFILETIME lpIdleTime,_Out_opt_  LPFILETIME lpKernelTime,_Out_opt_  LPFILETIME lpUserTime); 

It seems like it is getting the stuff I need, but I don't know how to actually use it or even make a unit test out of it, which I'd prefer before throwing it in the rest of my Source.cpp

I am completely lost. I've tried all sorts of things for the last few hours, but I can't even get a simple unit test compiling.

I feel like this comment has me on the right path, but I don't actually know what to do with it: How is CPU usage calculated?

edit #3:

I'm showing a Unit Test for Jeremy Friesner's code, as well as the completed logging tool that I was working on.

Test to monitor CPU Load

#include <Windows.h> #include <iostream> using namespace std;  static float CalculateCPULoad(); static unsigned long long FileTimeToInt64(); float GetCPULoad();   int main() {        int _c = 0;      while (_c == 0)     {         cout << GetCPULoad() * 100 << "\n";         Sleep(1000);     }      return 0; }   static float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks) {     static unsigned long long _previousTotalTicks = 0;     static unsigned long long _previousIdleTicks = 0;      unsigned long long totalTicksSinceLastTime = totalTicks - _previousTotalTicks;     unsigned long long idleTicksSinceLastTime = idleTicks - _previousIdleTicks;       float ret = 1.0f - ((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime) / totalTicksSinceLastTime : 0);      _previousTotalTicks = totalTicks;     _previousIdleTicks = idleTicks;     return ret; }  static unsigned long long FileTimeToInt64(const FILETIME & ft) {     return (((unsigned long long)(ft.dwHighDateTime)) << 32) | ((unsigned long long)ft.dwLowDateTime); }  // Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between // You'll need to call this at regular intervals, since it measures the load between // the previous call and the current one.  Returns -1.0 on error. float GetCPULoad() {     FILETIME idleTime, kernelTime, userTime;     return GetSystemTimes(&idleTime, &kernelTime, &userTime) ? CalculateCPULoad(FileTimeToInt64(idleTime), FileTimeToInt64(kernelTime) + FileTimeToInt64(userTime)) : -1.0f; } 

Completed Tool (all goes into your Source.cpp, then compile and run):

/* Resource Links: Calling memory info in c++:                             http://msdn.microsoft.com/en-us/library/aa366589%28VS.85%29.aspx I/O file handling in c++:                               http://www.cplusplus.com/doc/tutorial/files/ Date and Time in c++:                                   http://www.tutorialspoint.com/cplusplus/cpp_date_time.htm CPU Load Percent (Credit to Jeremy Friesner):           https://stackoverflow.com/questions/23143693/retrieving-cpu-load-percent-total-in-windows-with-c Everything else (too many to list):                     https://stackoverflow.com/ */   /* Performance Snapshot Tool  Grabs CPU load percent and basic Memory info from the system, and or the Windows Task manager  Designed to work with specifically Windows 7 and beyond  Ideology: Create a small executable program to retrieve and write to a log file a data sample from system performance in a single snapshot -- robust enough to be called multiple times per boot  The compiled .exe will be called by another program to run at an exact, specified time relative to the program that is calling it  Does 5 checks per second, every 200 milliseconds for a "Snapshot" of performance  Initial Code Author:    Anonymous Current Author: Anonymous Revision:           0.01 Date:               18/4/2014 */   //included libraries/functionality for input/output #include <iostream> #include <fstream> #include <windows.h> using namespace std;  //creates a static variable to convert Bytes to Megabytes #define MB 1048576  //functions to calculate and retrieve CPU Load information static float CalculateCPULoad(); static unsigned long long FileTimeToInt64(); float GetCPULoad();   //main program code loop int main() {     //Code block initialization for the memory referenced in the Kernel     MEMORYSTATUSEX memStat;     memStat.dwLength = sizeof (memStat);     GlobalMemoryStatusEx(&memStat);       //loads the SYSTEMTIME     SYSTEMTIME sysTime;     //Retrieves data so that we have a way to Get it to output when using the pointers     GetSystemTime(&sysTime);       //setting the I/O for our log file to be "myfile"     ofstream myfile;     // ios::out means that we're outputting data to the file     // ios::app means that all the data we're outputting goes to the end of that log file instead of the start     myfile.open("log.csv", ios::out | ios::app);       //a while loop that gathers and logs data every quarter of a second to gather 4 data points in one second     int counter = 0;     while (counter < 5)     {         //Timestamp + Memory Info, and eventually CPU Load percentage         myfile << sysTime.wHour << "." << sysTime.wMinute << "." << sysTime.wSecond << ", " << GetCPULoad() * 100 << "%, " << memStat.dwMemoryLoad << "%, " << memStat.ullTotalPhys / MB << ", " << memStat.ullAvailPhys / MB << ", " << memStat.ullTotalPageFile / MB << ", " << memStat.ullAvailPageFile / MB << ", " << memStat.ullTotalVirtual / MB << ", " << memStat.ullAvailVirtual / MB << ", " << memStat.ullAvailExtendedVirtual / MB << "\n";         //250 millisecond sleep delay          Sleep(200);         counter = counter + 1;     }         //close the log file before terminating the program         myfile.close();      return 0; //standard main() end of program terminator }  static float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks) {     static unsigned long long _previousTotalTicks = 0;     static unsigned long long _previousIdleTicks = 0;      unsigned long long totalTicksSinceLastTime = totalTicks - _previousTotalTicks;     unsigned long long idleTicksSinceLastTime = idleTicks - _previousIdleTicks;       float ret = 1.0f - ((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime) / totalTicksSinceLastTime : 0);      _previousTotalTicks = totalTicks;     _previousIdleTicks = idleTicks;     return ret; }  static unsigned long long FileTimeToInt64(const FILETIME & ft) {     return (((unsigned long long)(ft.dwHighDateTime)) << 32) | ((unsigned long long)ft.dwLowDateTime); }  // Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between // You'll need to call this at regular intervals, since it measures the load between // the previous call and the current one.  Returns -1.0 on error. float GetCPULoad() {     FILETIME idleTime, kernelTime, userTime;     return GetSystemTimes(&idleTime, &kernelTime, &userTime) ? CalculateCPULoad(FileTimeToInt64(idleTime), FileTimeToInt64(kernelTime) + FileTimeToInt64(userTime)) : -1.0f; } 
like image 502
kayleeFrye_onDeck Avatar asked Apr 17 '14 21:04

kayleeFrye_onDeck


People also ask

How do I check my CPU percentage in Windows?

Start by pressing CTRL + Shift + Esc on your keyboard. In the following window, click Task Manager. While in Task Manager, click the Performance tab. Here in the Performance tab, you can see how much of the CPU the computer is currently using.

How is CPU usage calculated in C?

Re: Get CPU usage (%) in a C programThe (pseudo-)file /proc/uptime contains two numbers: the system uptime, and the CPU time "used" (wasted) by the idle task, both in seconds. From this you can calculate the average CPU usage since boot.

How to calculate load percentage of CPU?

So in order to calculate a meaningful load percentage, you have to examine what percentage of time the CPU was idle during a particular interval of time.

How to get the CPU usage?

Those can be used to give you the CPU time used. To get the % CPU usage, you will need to divide it by the # of logical cores that the OS sees. To get get the CPU % usage you would need ( CPU time / # of cores / wall-clock time elapsed ), but otherwise correct.

How do I check the CPU load?

Open Task Manager and go to the Performance tab to monitor the CPU load. Right click the CPU graph on the right and select "Change graph to -> Logical processors". Double click the loop.vbs script you created to execute it.

How do I check how many logical processors my computer has?

Open Task Manager and go to the Performance tab to monitor the CPU load. Right click the CPU graph on the right and select "Change graph to -> Logical processors". Double click the loop.vbs script you created to execute it. Execute it N times, where N is the number of logical CPUs your computer has.


2 Answers

The reason it's popular to compute the load percentage over time is because CPUs don't really have variable speeds -- at any given instant, a CPU core is either processing instructions at its rated clock rate, or it's sitting idle, so an instantaneous measurement would only give you 0% or 100% (*), which isn't really what you want. So in order to calculate a meaningful load percentage, you have to examine what percentage of time the CPU was idle during a particular interval of time.

In any case, here's some code I use to get a CPU-usage value under Windows... just call GetCPULoad() at regular intervals (e.g. every 250mS or at whatever rate you like) and multiply by 100.0 to get a percentage:

#include <Windows.h>  static float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks) {    static unsigned long long _previousTotalTicks = 0;    static unsigned long long _previousIdleTicks = 0;     unsigned long long totalTicksSinceLastTime = totalTicks-_previousTotalTicks;    unsigned long long idleTicksSinceLastTime  = idleTicks-_previousIdleTicks;     float ret = 1.0f-((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);     _previousTotalTicks = totalTicks;    _previousIdleTicks  = idleTicks;    return ret; }  static unsigned long long FileTimeToInt64(const FILETIME & ft) {return (((unsigned long long)(ft.dwHighDateTime))<<32)|((unsigned long long)ft.dwLowDateTime);}  // Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between // You'll need to call this at regular intervals, since it measures the load between // the previous call and the current one.  Returns -1.0 on error. float GetCPULoad() {    FILETIME idleTime, kernelTime, userTime;    return GetSystemTimes(&idleTime, &kernelTime, &userTime) ? CalculateCPULoad(FileTimeToInt64(idleTime), FileTimeToInt64(kernelTime)+FileTimeToInt64(userTime)) : -1.0f; } 

(*) Okay, you might get a bit more resolution on a multicore system; e.g. if you measured instantaneous CPU usage on a quad-core CPU you might find that at that particular instant in time, three cores were idle and one core was active, and call that 25% load... and of course there are things like Intel's SpeedStep that actually varies the CPU's clock rate as a way to manage power consumption; but we'll ignore those complications for the time being :)

like image 150
Jeremy Friesner Avatar answered Nov 02 '22 13:11

Jeremy Friesner


The most popular proposed solution does not work for me on Win10 / Visual Studio 2010; the values obtained with that method do not seem to correlate with anything. Perhaps this is because, as noted in comments by Belogortseff, the GetSystemTimes function return for kernel time includes idle time.

See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724400(v=vs.85).aspx for a description of the GetSystemTimes function.

Furthermore, I'm not sure what happens when you assign the subtraction of two unsigned numbers, to another unsigned number. Seems like that should still be unsigned, but the proposed solution does a test on that value being less than zero.

I computed "headroom" this way:

Headroom = time spent in idle                   /          (Kernel time + User time)  

and then "load" as:

Load = 1 - Headroom 

Here is example code that you should be able to cut and paste into a VS project. If run under the VS debugger, it will display the results in the Output Window of the debugger via the OutputDebugString() call.

// DOSHeadroom.cpp : Defines the entry point for the console application. //  #include "stdafx.h" #include <Windows.h> #include <stdio.h> #include <atlstr.h> #include <iostream>     __int64 FileTimeToInt64 ( FILETIME & ft ) {     ULARGE_INTEGER foo;      foo.LowPart = ft.dwLowDateTime;     foo.HighPart = ft.dwHighDateTime;      return ( foo.QuadPart ); }   // UI Timer callback  VOID CALLBACK UITimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) {     #define NUMBER_OF_PROCESSORS (8)     #define PROCESSOR_BUFFER_SIZE (NUMBER_OF_PROCESSORS * 8)     static ULONG64 ProcessorIdleTimeBuffer [ PROCESSOR_BUFFER_SIZE ];     CString  ProcessorHeadroomPercentage;      FILETIME IdleTime, KernelTime, UserTime;     static unsigned long long PrevTotal = 0;     static unsigned long long PrevIdle = 0;     static unsigned long long PrevUser = 0;     unsigned long long ThisTotal;     unsigned long long ThisIdle, ThisKernel, ThisUser;     unsigned long long TotalSinceLast, IdleSinceLast, UserSinceLast;       // GET THE KERNEL / USER / IDLE times.       // And oh, BTW, kernel time includes idle time     GetSystemTimes( & IdleTime, & KernelTime, & UserTime);      ThisIdle = FileTimeToInt64(IdleTime);     ThisKernel = FileTimeToInt64 (KernelTime);     ThisUser = FileTimeToInt64 (UserTime);      ThisTotal = ThisKernel + ThisUser;     TotalSinceLast = ThisTotal - PrevTotal;     IdleSinceLast = ThisIdle - PrevIdle;     UserSinceLast = ThisUser - PrevUser;     double Headroom;     Headroom =  (double)IdleSinceLast / (double)TotalSinceLast ;     double Load;     Load = 1.0 - Headroom;     Headroom *= 100.0;  // to make it percent     Load *= 100.0;  // percent      PrevTotal = ThisTotal;     PrevIdle = ThisIdle;     PrevUser = ThisUser;      // print results to output window of VS when run in Debug     ProcessorHeadroomPercentage.Format(_T(" Headroom: %2.0lf%%   Load: %2.0lf%%\n"), Headroom, Load);     OutputDebugString(ProcessorHeadroomPercentage);  }    void SetupMyTimer (void) {     // set up a timer to periodically update UI, specifically to support headroom display     // I'll use a timerQueue for this application     // Create the timer queue.     HANDLE   hTimerQueue;     HANDLE   hUITimer;     enum     { UI_TIMER_RATE = 1000 };  // should happen every 1000 ms or 1Hz.  That should be fast enough      hTimerQueue = NULL;     hUITimer = NULL;     hTimerQueue = CreateTimerQueue();     CreateTimerQueueTimer( &hUITimer, hTimerQueue,           (WAITORTIMERCALLBACK)UITimerRoutine, NULL, 0, UI_TIMER_RATE, 0); //the 1000 means wait 1000ms for first call  }   int _tmain(int argc, _TCHAR* argv[]) {     SetupMyTimer();     Sleep(10000);     return 0; } 

I have the UITimerHandler called once a second by a TimerQueue. I figured that was a reasonable period over which processor utilization could be estimated.

like image 42
El Ronaldo Avatar answered Nov 02 '22 12:11

El Ronaldo