程序CPU使用率探讨
前言
一般好的软件程序是不应该占用太多CPU时间和内存空间的,一般在自己的学习过程中,我们常常忽略这一点,虽然功能实现没有问题,但是程序占用太多CPU时间,这在实际开发中是不允许的,一个好的程序员也应该注意这个问题。本文就CPU使用率问题做一些简单介绍,为开发稳定健壮的程序提供参考。
简单例子
#include <iostream> using namespace std;
int _tmain(int argc, _TCHAR* argv[]) { while (1) {
}
system("pause"); return 0; } |
在任务管理器中可以看到该程序的CPU使用率:
本次程序在双核Windows 64位系统下测试,也就是说该程序占用了一半的CPU。这个很容易理解,while循轮询CPU时间太快,CPU需要不断响应,造成很高的CPU使用率。很多时候我们想到在while循环中让程序休息一下,代码如下:
#include <Windows.h> #include <iostream> using namespace std;
int _tmain(int argc, _TCHAR* argv[]) { while (1) { Sleep(1); }
system("pause"); return 0; } |
在任务管理器中可以看到该程序的CPU使用率:
这样可以看到让程序休息一会,占用CPU的使用时间就大为减少,这样对于一些实时性要求不是很高的程序,这样处理是可以的。
单线程测试
前面的例子有点简单,在实际应用中,这个问题多体现在多线程中。先写个单线程测试:
#include <windows.h> #include <process.h> #include <iostream> using namespace std;
unsigned __stdcall ThreadFunc(void* pArguments) { // 执行线程任务 while (1) { cout << "thread is running..." << endl; }
// 中止线程 _endthreadex(0); return 0; }
int _tmain(int argc, _TCHAR* argv[]) { HANDLE hThread;
// 启动线程 hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, NULL, 0, NULL);
// 等待线程完成 WaitForSingleObject(hThread, INFINITE);
// 关闭线程句柄 CloseHandle(hThread);
system("pause"); return 0; } |
在任务管理器中可以看到该程序的CPU使用率:
如果把下面语句注释掉:
unsigned __stdcall ThreadFunc(void* pArguments) { // 执行线程任务 while (1) { //cout << "thread is running..." << endl; }
// 中止线程 _endthreadex(0); return 0; } |
会发现CPU使用率又达到50%,综合前面,可以看出,让线程输出或者Sleep可以大大减少占用CPU时间,其中Sleep效果更优。
多线程测试
#include <windows.h> #include <process.h> #include <iostream> using namespace std;
unsigned __stdcall ThreadFunc(void* pArguments) { // 执行线程任务 while (1) { }
// 中止线程 _endthreadex(0); return 0; }
int _tmain(int argc, _TCHAR* argv[]) { const int nThreadNum = 20; HANDLE hThread[nThreadNum];
// 启动线程 for (int i = 0; i < nThreadNum; ++i) { hThread[i] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, NULL, 0, NULL); }
// 等待线程完成 for (int i = 0; i < nThreadNum; ++i) { WaitForSingleObject(hThread[i], INFINITE); }
// 关闭线程句柄 for (int i = 0; i < nThreadNum; ++i) { CloseHandle(hThread[i]); }
system("pause"); return 0; } |
在任务管理器中可以看到该程序的CPU使用率:
可见,这几乎占据了CPU的所有时间,系统卡住了。可见,在多线程中,while循环的使用更需要谨慎。
同样我们让每个线程都输出
cout<< "threadis running..."<< endl;
结果得到优化:
同样我们让每个线程都睡眠1ms,结果更化:
至此,我们可以总结一下,对于实时性要求不是很高的程序,我们在使用while循环的时候要让执行体睡眠或者输出都可以大大减少程序占用CPU时间,但睡眠效果更优,但许多时候不需要输出,所以睡眠是一种不错的选择。
但是睡眠也要注意:对于实时工作线程,睡眠1ms为佳;对于主线程(通常为控制台界面线程),为了保持运行,一般在main函数中加入while循环,在while里面sleep多久虽然理论上是一样的,但为了让每个sleep运行一点,个人习惯使用Sleep(10000)。