一种通过代码(cmd命令行)准确获取cpu的使用率的方法

项目需要获取cpu的使用率,还需要跟任务管理器保持一致.

先是百度了一大圈,说是用GetSystemTimes这个api,来获取cpu总时间和空闲时间,然后做减法,每一段时间循环计算来实现的。

下面是代码:

__int64 CompareTime(FILETIME time1, FILETIME time2)
{
	__int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime;
	__int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime;
	return (b - a);
}
void TestDiskManager::GetCpuInfo() 
{
	FILETIME idleTime;//空闲时间 
	FILETIME kernelTime;//核心态时间 
	FILETIME userTime;//用户态时间 
	bool res;
	res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
	cout << "GetSystemTimes(&, &, &) = " << res << endl << endl;

	HANDLE hEvent;
	FILETIME pre_idleTime;
	FILETIME pre_kernelTime;
	FILETIME pre_userTime;

	pre_idleTime = idleTime;
	pre_kernelTime = kernelTime;
	pre_userTime = userTime;

	hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	//初始值为nonsignaled,并且每次触发后自动设置为nonsignaled

	while (1) {
		WaitForSingleObject(hEvent, 1000);//等待500毫秒

		res = GetSystemTimes(&idleTime, &kernelTime, &userTime);

		__int64 idle = CompareTime(pre_idleTime, idleTime);
		__int64 kernel = CompareTime(pre_kernelTime, kernelTime);
		__int64 user = CompareTime(pre_userTime, userTime);

		int cpu_occupancy_rate = (kernel + user - idle) * 100 / (kernel + user);
		//(总的时间 - 空闲时间)/ 总的时间 = 占用CPU时间的比率,即占用率

		int cpu_idle_rate = idle * 100 / (kernel + user);
		//空闲时间 / 总的时间 = 闲置CPU时间的比率,即闲置率 

		int cpu_kernel_rate = kernel * 100 / (kernel + user);
		//核心态时间 / 总的时间 = 核心态占用的比率 

		int cpu_user_rate = user * 100 / (kernel + user);
		//用户态时间 / 总的时间 = 用户态占用的比率 

		cout << left << setw(15) << "CPU占用率:" << cpu_occupancy_rate << "%" << endl
			<< setw(15) << "CPU闲置率:" << cpu_idle_rate << "%" << endl
			<< setw(15) << "核心态占比率:" << cpu_kernel_rate << "%" << endl
			<< setw(15) << "用户态占比率:" << cpu_user_rate << "%" << endl << endl;

		pre_idleTime = idleTime;
		pre_kernelTime = kernelTime;
		pre_userTime = userTime;
	}

}
void TestDiskManager::GetCpuInfo2() 
{

    static FILETIME pre_idle_time;
    static FILETIME pre_kernel_time;
    static FILETIME pre_user_time;

    // 空闲时间
    FILETIME idle_time;
    // 内核时间
    FILETIME kernel_time;
    // 用户时间
    FILETIME user_time;
    BOOL ret = GetSystemTimes(&idle_time, &kernel_time, &user_time);

    int idle = CompareFileTime(&pre_idle_time, &idle_time);
    int kernel = CompareFileTime(&pre_kernel_time, &kernel_time);
    int user = CompareFileTime(&pre_user_time, &user_time);

    float rate = (kernel + user - idle) / (1.0 * (kernel + user));

    pre_idle_time = idle_time;
    pre_kernel_time = kernel_time;
    pre_user_time = user_time;
	cout << left << setw(15) << "CPU占用率:" << rate << "%" << endl;


}

  然后发现,跟任务管理器显示偏差很大,然后就去搜索原因,百度了一圈也没找到,都是类似的解决,没人说出个所以然来,最后在stackoverflow找到一个靠谱的答案,原文:

Why is this method to obtain CPU utilization produces results 2 times lower than that from the Task Manager?

相关截图:编辑

 大意是讲taskmgr(任务管理器)是超线程感知的。假设您有 2 个物理内核,总共有 4 个逻辑内核。将2个内核置于满负荷状态,任务列表将显示100%,而您的方法将显示50%,当所有4个逻辑内核都填满时,任务列表仍将显示100%,然后您的方法也将显示100%。

文中也没给解决方案,于是继续搜索。最后在stack大佬的帮助下,找到了这篇文章:

PerformanceCounter reporting higher CPU usage than what's observed

截图:

编辑

 大意是讲,使用了错误的参数。使用“Processor Information”而不是“Processor”。

结合之前找到的命令:

typeperf "\Processor(_Total)\% Processor Time"

稍作修改为:

typeperf "\Processor Information(_Total)\% Processor Utility"

试了下果然可行,数据什么的都很准确,如下图:

编辑

至此,基本上算是可以交差了。

不过在实现的过程中发现,做C++,面向百度编程已经不行了,必须要面向谷歌编程了。国内C++相关的干货实在太少,虽然天下文章一大抄,但是无脑抄就不太好了。

同名博客:一种通过代码(cmd命令行)准确获取cpu的使用率的方法_还在水里游的博客-CSDN博客

posted on 2022-09-08 19:36  阿狸的知识库  阅读(534)  评论(0编辑  收藏  举报