1.1 使CPU占用曲线为正弦曲线
参考《编程之美–1.1 让CPU占用时间听你指挥》
问题分析:
这里的CPU占用曲线为Windows任务管理器中呈现的。在任务管理器器的一个刷新周期内,CPU忙(执行应用程序)的时间和刷新周期总时间的比率,就是CPU占用率。
根据这个原理,我们可以通过在一段时间内调整CPU忙和闲的时间来使CPU占用曲线呈现所想要呈现的波形。
忙:用循环来表示忙的停止时间应该用GetTickCount()函数来确定。GetTickCount()函数可以得到“系统启动到现在”所经历时间的毫秒值;
闲:用Sleep()函数表示,这里Sleep(10),因为10毫秒接近Windows的调度时间片。如果太小则会导致线程不断被唤醒和挂起,影响内核时间的稳定性。
忙的时间长短应根据正弦曲线在采样点的值决定,得到忙时间函数:
const int SAMPLE_COUNT = 200; //每个周期的采样点数
const double PI = 3.1415926535; //派值
const int TOTAL_AMPLITUDE = 30; //正弦函数振幅
DWORD busySpan[SAMPLE_COUNT];
double radianIncrement = 2.0/(double)SAMPLE_COUNT; //每个采样间隔的弧度增量
for(int i = 0; i<SAMPLE_COUNT; i++){
busySpan[i] = (DWORD)(amplitude + (sin(PI*radian)*amplitude)); //计算当前采样点的幅度,注意正弦函数应上移
radian += radianIncrement;
}
根据忙时间数组循环忙闲:
for(int j = 0;; j = (j + 1)%SAMPLE_COUNT){
startTime = GetTickCount();
while((GetTickCount() - startTime) <= busySpan[j])
;
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
要注意目前主流计算机搭载的CPU均为多核,所以应指定某个核心来运行程序,使得效果不致太差:
SetThreadAffinityMask(GetCurrentThread(),1);
全部代码:
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
const int SAMPLE_COUNT = 200;
const double PI = 3.1415926535;
const int TOTAL_AMPLITUDE = 30;
int main()
{
SetThreadAffinityMask(GetCurrentThread(),1);
DWORD busySpan[SAMPLE_COUNT];
int amplitude = TOTAL_AMPLITUDE/2;
double radian = 0.0;
double radianIncrement = 2.0/(double)SAMPLE_COUNT;
for(int i = 0; i<SAMPLE_COUNT; i++){
busySpan[i] = (DWORD)(amplitude + (sin(PI*radian)*amplitude));
radian += radianIncrement;
}
DWORD startTime = 0;
for(int j = 0;; j = (j + 1)%SAMPLE_COUNT){
startTime = GetTickCount();
while((GetTickCount() - startTime) <= busySpan[j])
;
Sleep(TOTAL_AMPLITUDE - busySpan[j]);
}
return 0;
}