C++第四十二篇 -- CPU Usage
前言
目的:读取并控制CPU占用率
近期在做CPU Usage方面的事情,让CPU以一种高占用率的状态运行一定的时间,需要读取CPU各个核的占用率,网上关于这方面的资料好少,FQ也只找到了一个WMI的方法,但是感觉对比任务管理器里面的结果偏小。目前也只能读取CPU总的占用率,和任务管理器看起来差不多,也不是完全相同。
虽然还没有实现结果,但是想记录一下历程。
参考链接:
https://blog.csdn.net/wangting627/article/details/22931337
https://blog.csdn.net/fyxichen/article/details/50577580
内容
1. 任务管理器查看CPU占用率。
方法一:

方法二:


2. C++读取CPU的占用率
原理:先读取一次CPU的当前的空闲时间,内核时间和用户时间,间隔一秒,再次读取三个时间,经过公式演算,得到CPU在这一秒内的占用率。
第一次读取:

FILETIME ftIdle, ftKernel, ftUser;
BOOL flag = FALSE;
if (flag = GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
{
m_fOldCPUIdleTime = FileTimeToDouble(&ftIdle);
m_fOldCPUKernelTime = FileTimeToDouble(&ftKernel);
m_fOldCPUUserTime = FileTimeToDouble(&ftUser); }
return flag;
第二次读取:

FILETIME ftIdle, ftKernel, ftUser;
//检索系统定时信息,对于多处理器系统,返回值是各处理器总和的时间
//参数1:空闲时间
//参数2:内核时间
//参数3:用户时间
//函数成功,返回值为非零。函数失败,返回值为零
if (GetSystemTimes(&ftIdle, &ftKernel, &ftUser))
{
double fCPUIdleTime = FileTimeToDouble(&ftIdle);
double fCPUKernelTime = FileTimeToDouble(&ftKernel);
double fCPUUserTime = FileTimeToDouble(&ftUser);}
计算占用率:

//CPU使用率 = (总的时间-空闲时间) / 总的时间
nCPUUseRate = (int)(100.0 - (fCPUIdleTime - m_fOldCPUIdleTime) / (fCPUKernelTime - m_fOldCPUKernelTime + fCPUUserTime - m_fOldCPUUserTime)*100.0);
3. 控制CPU占用率
原理:CPU的占用率 = (CPU总时间 - CPU空闲时间)/ CPU总时间。
举几个例子看看:
| 占用率 | num值 | 空闲时间:运行时间 |
| 50% | 1 | 1:1 |
| 66.7% | 2 | 1:2 |
| 80% | 4 | 1:4 |
| 90% | 9 | 1:9 |
如果想要控制CPU的占用率是50%,那么就设置num = 1,空闲时间和运行时间的比例为1:1。不过这些都有个前提是,电脑中并没有运行其他的程序。但是显然不可能,所以这个占用率也只是个大概。并且想要数据比较准确,一秒之内的空闲和运行最好是间隔运行,如果控制前0.5s运行,后0.5秒Sleep,效果也是不好的,在代码中设置的是0.1s休息。

int busytime = 100;
int idletime = busytime;
long starttime = 0;
while (true)
{
starttime = GetTickCount();
//std::cout<<starttime<<std::endl;//调试用
while ((GetTickCount() - starttime) <= busytime * num)
;
Sleep(idletime);
}
4. 效果图
以1:9的代码运行结果如下:

可以看到其实任务管理器中的值每隔一秒刷新一次,我写的程序是每隔一秒刷新一次,然后任务管理器中的值看起来比代码中的偏高一些,大胆猜测一下是因为我的程序也在运行,运行过程中也会增加占用率。
5. WMI读取CPU各个核的使用率
代码是google找到的,链接我忘了,后续找到补上,需要FQ

bool getCpuLoadInfo() {
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
return 0; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres)) {
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 0; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres)) {
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 0; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres)) {
cout << "Could not connect. Error code = 0x" << hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 0; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres)) {
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
IWbemClassObject *pclsObj;
int i;
//while (1) {
i = 1;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres)) {
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
ULONG uReturn = 0;
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (0 == uReturn) {
break;
}
VARIANT vtProp;
// Get the value of the Name property
//hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
wcout << " CPU Usage of CPU " << i << " : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);
//IMPORTANT!!
pclsObj->Release();
i++;
}
//}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
//pclsObj->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
以1:9的比例
先看一下它运行之后的效果图:

看右侧任务管理器中的图形,自始至终没有低于90%,可是WMI读出来的却有70%的出现,况且我自己设置的比例是1:9,自己加的占用率,所以感觉WMI读出来的可能有点不合理,偏低了。看资料有几种计算方法,也不知道哪个正确。
另外分享一下WMI的小技巧。文中代码就是找到“PercentProcessorTime”的值,作为CPU的占用率。一起试着在Windows中手动找一找呗。
a. win+R输入"wbemtest"








总结
问题:
试了多种方法,无法知道哪个结果更加权威,也或者是了解并不深,WMI内部的机制也并不是很清楚,任务管理器里面的计算机制是什么也不清楚,还得继续学习进步。这方面的资料很少,因此学习总结做一下分享。
源码:
目前还没有实现每个核的占用率读取,等后续学习深入补上源码。
C++第四十二篇 -- CPU Usage的更多相关文章
- Python之路(第四十二篇)线程相关的其他方法、join()、Thread类的start()和run()方法的区别、守护线程
一.线程相关的其他方法 Thread实例对象的方法 # isAlive(): 返回线程是否活动的. # getName(): 返回线程名. # setName(): 设置线程名. threadin ...
- Android UI开发第四十二篇——实现实现易信的圆形图像和对话列表的图像显示部分
显示图像时,很多个性化显示,圆形或圆角.气泡等等,我们这一篇文章探讨一下圆形和气泡的显示,仿照易信中的实现,先看下效果图: 代码: public class RoundImageView extend ...
- 第四十二篇、自定义Log打印
1.在Xcode 8出来之后,需要我们去关闭多余的日志信息打印 2.在开发的过程中,打印调试日志是一项比不可少的工程,但是在iOS 10中NSLog打印日志被屏蔽了,就不得不使用自定义Log 3.去掉 ...
- 第四十二篇 入门机器学习——Numpy的基本操作——索引相关
No.1. 使用np.argmin和np.argmax来获取向量元素中最小值和最大值的索引 No.2. 使用np.random.shuffle将向量中的元素顺序打乱,操作后,原向量发生改变:使用np. ...
- Spring Cloud第十二篇 | 消息总线Bus
本文是Spring Cloud专栏的第十二篇文章,了解前十一篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring ...
- 第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗?
第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗? 几个月前(回到3月份),您可能还记得我在这个系列的52件东西中发布了第23件(可以在这里找到).这篇文章的标题是& ...
- 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)
解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...
- 第十二篇 SQL Server代理多服务器管理
本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...
- 第十二篇 Integration Services:高级日志记录
本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
随机推荐
- 【NX二次开发】Block UI 指定方位
属性说明 属性 类型 描述 常规 BlockID String 控件ID Enable Logical 是否可操作 Group ...
- 12:media配置以及后端指定资源暴露
django需要用到的静态文件默认都是放在static目录下 而针对后期用户上传的静态文件也应该统一存储 # media配置:规定用户上传的静态文件存储位置 MEDIA_ROOT = os.path. ...
- Java后端精选技术:SpringBoot配置读取
在早前的博客中曾经写过 Spring 程序通过 Bean 映射实现配置信息的读取. 在SpringBoot 框架中读取配置的方式变得非常多样,这导致读者在搜寻资料时反而容易迷糊. 到底,SpringB ...
- 文字识别OCR开源框架的对比--Tesseract vs EasyOCR
前言: OCR文字识别在目前有着比较好的应用,也出现了很多的文字识别软件,但软件是面向用户的.对于我们技术人员来说,有时难免需要在计算机视觉任务中加入文字识别,如车牌号识别,票据识别等,因此软件对 ...
- linux下 大日志文件查看与搜索---less
场景 有一个几十m的大日志文件,里边的记录是按时间排序的. 现在需要找到其中,不知道在什么位置的一条错误消息.这时候,想把内容拷出来都费劲,就算拷出来了,一般的编辑器也难以hold住这么大的文件.这时 ...
- Java安全之反序列化回显研究
Java安全之反序列化回显研究 0x00 前言 续上文反序列化回显与内存马,继续来看看反序列化回显的方式.上篇文中其实是利用中间件中存储的Request 和Response对象来进行回显.但并不止这么 ...
- C#WebApi的创建与发布
VS中新建项目-Web-ASP.NET Web应用程序 然后确定,选择空模版就可以了,勾上Webapi(也可以选择webapi模板,这样生成的文件比较多) 添加好之后Controllers和Model ...
- 手把手教你IDEA连接码云(Gitee)
目录 前言 一.下载.安装git 1.打开git官网,选择你的操作系统 2.根据你的系统位数选择相应的版本下载 3.安装 4.配置全局的用户名.邮箱 5.在idea中配置git目录 二.配置Gitee ...
- Jenkins CI&CD 自动化发布项目实战(下篇)
Jenkins CI&CD 自动化发布项目实战(下篇) 作者 刘畅 时间 2020-12-04 实验环境 centos7.5 主机名 ip 服务配置 软件 gitlab 172.16.1.71 ...
- lvm脚本
# 2 SWAP 20GB SWAP # 3 /usr/sap 50GB /usr/sap # 4 Shared 1 x 512 GiB /hana/shared # 5.6 Log 2 x 300 ...