Retrieving CPU Load Percent total in Windows with C++

后端 未结 3 779
余生分开走
余生分开走 2020-12-13 01:04

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

相关标签:
3条回答
  • 2020-12-13 01:22

    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.

    0 讨论(0)
  • 2020-12-13 01:29

    This code is take for Cpu Usage

    FILETIME prevSysIdle, prevSysKernel, prevSysUser;
    
    int getUsage(double &val)
    {
        FILETIME sysIdle, sysKernel, sysUser;
        // sysKernel include IdleTime
        if (GetSystemTimes(&sysIdle, &sysKernel, &sysUser) == 0) // GetSystemTimes func FAILED return value is zero;
            return 0;
    
        if (prevSysIdle.dwLowDateTime != 0 && prevSysIdle.dwHighDateTime != 0)
        {
            ULONGLONG sysIdleDiff, sysKernelDiff, sysUserDiff;
            sysIdleDiff = SubtractTimes(sysIdle, prevSysIdle);
            sysKernelDiff = SubtractTimes(sysKernel, prevSysKernel);
            sysUserDiff = SubtractTimes(sysUser, prevSysUser);
    
            ULONGLONG sysTotal = sysKernelDiff + sysUserDiff;
            ULONGLONG kernelTotal = sysKernelDiff - sysIdleDiff; // kernelTime - IdleTime = kernelTime, because sysKernel include IdleTime
    
            if (sysTotal > 0) // sometimes kernelTime > idleTime
                val = (double)(((kernelTotal + sysUserDiff) * 100.0) / sysTotal);
        }
    
        prevSysIdle = sysIdle;
        prevSysKernel = sysKernel;
        prevSysUser = sysUser;
    
        return 1;
    }
    
    
    // TIME DIFF FUNC
    ULONGLONG SubtractTimes(const FILETIME one, const FILETIME two)
    {
        LARGE_INTEGER a, b;
        a.LowPart = one.dwLowDateTime;
        a.HighPart = one.dwHighDateTime;
    
        b.LowPart = two.dwLowDateTime;
        b.HighPart = two.dwHighDateTime;
    
        return a.QuadPart - b.QuadPart;
    }
    
    0 讨论(0)
  • 2020-12-13 01:37

    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 :)

    0 讨论(0)
提交回复
热议问题