《编程之美》读书随笔之一:让CPU占有率曲线听你指挥

来源:互联网 发布:心动网络官网电脑版 编辑:程序博客网 时间:2024/05/19 00:55

这个问题的描述如下:写一个程序,让用户来觉得Windows的任务管理器(Task Messager)上的CPU占有率,编程语言不限。程序越精简越好,可以实现下面的功能:

第一、CPU的占有率固定在50%,为一条直线。

第二、CPU占有率为一条直线,占有率由命令行参数决定(范围是1-100)。

第三,CPU的占有率是一条正弦曲线。

在解这个题目之前,要先了解一下什么是CPU的占有率,从“占有”这两个字来看,CPU的占有率应该是CPU忙碌的时间占总时间的比率。题目中让我们控制CPU的占有率,就是让我们控制CPU什么时候忙碌,什么时候空闲,让它听从我们的指挥。

很容易,我们就想到了通过循环和判断来实现这个功能,在一半的时间内,我们让CPU运行自己的程序,另外一半,使用sleep,让CPU空闲,可以运转其他的程序,这个时间控制使用一个变量来控制,让变量自增或者自减。

解法一:在《编程之美》这本书里面讲的很清楚,循环确实可以做到,但是我们如何知道一个空循环所需要的时间呢,这个就需要自己估算了,在计算机中,任何程序到底层之后都会转换成机器指令,在接近机器指令的最近的语言就是汇编语言,我们可以通过分析汇编语言来分析一个空循环所需的时间。

LOOP:mov dx i         ;将i放入寄存器dx中inc dx             ;将dx自加1mov i dx         ;将寄存器中的值赋值给icmp i n           ;判断i的值是否为njl loop             ;循环

从这几行汇编语言中,我们可以看出来,一次循环需要运行5条机器指令,假设我们每个时钟周期可以执行两条以上的代码,CPU是频率是2.6GHZ,这是我的计算机CPU频率,这样没一秒钟就可以执行上述代码(2 600 000 000*2)/5 = 1 040 000 000次。但是我们的CPU空闲时间怎么确定呢,是不是直接就是一秒,也就是sleep(1000)就行了,答案是否。原因是在Windows下,CPU线程切换需要时间。在书上说的,CPU切换的时间片差不多就是10毫秒,这样我们就可以设定为sleep(10),得到的程序如下:

for(;;){for(int i = 0; i < 10400000;i++);Sleep(10);}

不断调整循环次数,可以保证CPU的占有率曲线是一天直线,但是不是很稳定。该方法有一个很大的缺点就是,一旦换了一个CPU,我们必须重新计算循环次数。现在就需要一个动态的循环次数来适应CPU。

解法二:使用GetTickCount()函数得到系统从启动到现在所经历的毫秒数,也就是时间。代码如下:

void fun1(){int busyTime = 10;int idleTime = busyTime * 1.0; //调整这个1.0的值,以达到50%的标准,不同的计算机上是不同的。int ret = SetThreadAffinityMask(GetCurrentThread(),0x00000001);//使这个程序跑在第一个CPU核心INT64 startTime = 0;while (1){startTime = GetTickCount(); while((GetTickCount() - startTime) <= busyTime);Sleep(idleTime);}}

这种方法貌似可以,但是如果在操作系统中,其他进程也占有CPU资源的话,假如其他程序占有10%的CPU资源,那么本程序只能使用40%的CPU资源才能达到效果。这也不算是完全动态。