Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 正在使用C+;检索Windows中的CPU总负载百分比+;_C++_Windows_Visual Studio 2013_Cpu Usage - Fatal编程技术网

C++ 正在使用C+;检索Windows中的CPU总负载百分比+;

C++ 正在使用C+;检索Windows中的CPU总负载百分比+;,c++,windows,visual-studio-2013,cpu-usage,C++,Windows,Visual Studio 2013,Cpu Usage,我一直在使用这个工具来快速记录一些系统统计数据,如内存信息和cpu负载百分比(如任务管理器中显示的)。我似乎已经处理好了内存和日志部分,但计算CPU百分比非常困难:(我发现了很多关于检查CPU信息的方法的信息,但是除了摘要之外,我发现的代码样本几乎没有一个是经过编译的,或者是经过良好注释的,所以我很难找到一种方法来实现这一点。我已经阅读了很多关于获取CPU时间之类的堆栈溢出问题,但是我还没有把这篇文章放进去他们在一起 也许我没有抓住要点,但似乎一种流行的解决方法是,在每次检查之间至少间隔200m

我一直在使用这个工具来快速记录一些系统统计数据,如内存信息和cpu负载百分比(如任务管理器中显示的)。我似乎已经处理好了内存和日志部分,但计算CPU百分比非常困难:(我发现了很多关于检查CPU信息的方法的信息,但是除了摘要之外,我发现的代码样本几乎没有一个是经过编译的,或者是经过良好注释的,所以我很难找到一种方法来实现这一点。我已经阅读了很多关于获取CPU时间之类的堆栈溢出问题,但是我还没有把这篇文章放进去他们在一起

也许我没有抓住要点,但似乎一种流行的解决方法是,在每次检查之间至少间隔200ms,查询CPU两次,以帮助避免出现所谓的“分辨率”问题?是的!我该怎么做呢?:(我在语法上受到挑战,D:

我将与大家分享我的源代码,这样你们就可以看到我到目前为止一直在做什么。这一切都在一个。cpp,我使用的是适用于C++
的VS2013 Express,它只适用于适用于多核CPU的Windows

提前警告:对于代码中的所有注释,我感到非常抱歉:x此外,如果复制此代码并运行它,它将生成一个名为log.CSV的.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
}
它似乎得到了我所需要的东西,但我不知道如何实际使用它,甚至不知道如何用它进行单元测试,在将它放入我的Source.cpp的其余部分之前,我更愿意这样做

我完全迷路了。在过去的几个小时里,我尝试了各种各样的方法,但我甚至不能得到一个简单的单元测试编译

我觉得这句话让我走上了正确的道路,但我不知道该怎么办:

编辑#3:

我展示了Jeremy Friesner代码的单元测试,以及我正在使用的完整的日志工具

监控CPU负载的测试

#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;
}
#包括
#包括
使用名称空间std;
静态浮点计算cpuload();
静态无符号长文件timeToInt64();
float GetCPULoad();
int main()
{   
int _c=0;
而(_c==0)
{

cout计算一段时间内的负载百分比之所以流行,是因为CPU并没有真正的可变速度——在任何给定的时刻,CPU核心要么以其额定时钟速率处理指令,要么处于空闲状态,因此瞬时测量只能给你0%或100%(*)因此,为了计算有意义的负载百分比,您必须检查CPU在特定时间间隔内空闲的时间百分比

在任何情况下,我都会使用下面的一些代码来获取Windows下的CPU使用率值……只需定期调用GetCPULoad()(例如,每250mS或以您喜欢的任何速率),然后乘以100.0即可得到一个百分比:

#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;
}
#包括
静态浮点CalculateCPULoad(无符号长idleTicks、无符号长totalTicks)
{
静态无符号长时间_previousTotalTicks=0;
静态无符号long long_previousIdleTicks=0;
无符号长TotalTicksLastTime=totalTicks-\u previousTotalTicks;
无符号长IDLECTICKSSINCELASTIME=IDLECTICKS-\u先前的IDLECTICKS;
float-ret=1.0f-((totalTicksSinceLastTime>0)?((float)IdleticksSincellastTime)/totalTicksSinceLastTime:0);
_previousTotalTicks=totalTicks;
_以前的IDLECTIKS=IDLECTIKS;
返回ret;
}

静态unsigned long FileTimeToInt64(const FILETIME&ft){return((unsigned long)(ft.dwHighDateTime))此代码用于Cpu使用

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;
}

最流行的建议解决方案在Win10/Visual Studio 2010上对我不起作用;使用该方法获得的值似乎与任何东西都不相关。这可能是因为,正如Belogortseff在评论中所指出的,GetSystemTimes函数返回的内核时间包括空闲时间

有关GetSystemTimes函数的说明,请参阅

此外,我不确定当你将两个无符号数的减法赋值给另一个无符号数时会发生什么。看起来这仍然应该是无符号的,但建议的解决方案对小于零的值进行了测试

我这样计算“净空”:

Headroom = time spent in idle
                  / 
        (Kernel time + User time) 
然后“加载”为:

下面是您应该能够剪切并粘贴到VS项目中的示例代码。如果在VS调试器下运行,它将通过OutputDebugString()调用在调试器的输出窗口中显示结果

//DOSHeadroom.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#包括
#包括
__int64 FileTimeToInt64(FILETIME和ft)
{
ULARGE_整数foo;
foo.LowPart=ft.dwLowDateTime;
foo.HighPart=ft.dwHighDateTime;
返回(foo.QuadPart);
}
//用户界面计时器回调
无效回调UITimeRoutine(PVOID lpParam,布尔TimerOrWaitFired)
{
#定义处理器的数量(8)
#定义处理器缓冲区大小(处理器数量*8)
静态ULONG64 ProcessorIdleTimeBuffer[处理器缓冲区大小];
CString处理器头枕;
FILETIME空闲时间、内核时间、用户时间;
静态无符号long-long-PrevTotal=0;
静态无符号长PrevIdle=0;
静态无符号长PrevUser=0;
未签名的long-long-ThisTotal;
无符号长ThisIdle、ThisKernel、ThisUser;
无符号长-长TotalSinceLast、IdleSinceLast、UserSinceLast;
//获取内核/用户/空闲时间。
//哦,顺便说一句,内核时间包括空闲时间
GetSystemTimes(&IdleTime,&KernelTime,&UserTime);
ThisIdle=FileTimeToInt64(IdleTime);
ThisKernel=FileTimeToInt64(KernelTime);
ThisUser=FileTimeToInt64(UserTime);
ThisTotal=ThisKernel+ThisUser;
TotalSinceLast=此总计-上一个总计;
IdleSinceLast=此空闲-前空闲;
UserSinceLast=Th
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;
}
Headroom = time spent in idle
                  / 
        (Kernel time + User time) 
Load = 1 - Headroom
// 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;
}