【解法三】能动态适应的解法

代码清单 1-3

//C# code

static void MakeUsage(float level)

{

  PerformanceCounter p = new PerformanceCounter("Processor", "% Processor Time",

    "_Total");

while (true)

{

   if (p.NextValue() > level)

       System.Threading.Thread.Sleep(10);

 }

}

可以看到,上面的解法能方便地处理各种 CPU 使用率参数。这个程序可以解答前面提

到的问题 2

有了前面的积累,我们应该可以让任务管理器画出优美的正弦曲线了,见下面的代码。

【解法四】正弦曲线

代码清单 1-4

//C++ code to make task manager generate sine graph

#include "Windows.h"

#include "stdlib.h"

#include "math.h"

const

const

const

const

double SPLIT = 0.01;

int COUNT = 200;

double PI = 3.14159265;

int INTERVAL = 300;

int _tmain(int argc, _TCHAR* argv[])

{

   DWORD busySpan[COUNT]; //array of busy times

   DWORD idleSpan[COUNT]; //array of idle times

   int half = INTERVAL / 2;

   double radian = 0.0;

   for(int i = 0; i < COUNT; i++)

   {

       busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));

       idleSpan[i] = INTERVAL - busySpan[i];

       radian += SPLIT;

   }

DWORD startTime = 0;

int j = 0;

while (true)

{

   j = j % COUNT;

   startTime = GetTickCount();

   while ((GetTickCount() - startTime) <= busySpan[j]) ;

   Sleep(idleSpan[j]);

   j++;

}

return 0;

}

讨论

如果机器是多 CPU,上面的程序会出现什么结果?如何在多个 CPU 时显示同样的状

态?例如,在双核的机器上,如果让一个单线程的程序死循环,能让两个 CPU 的使用率达

 50%的水平么?为什么?

 CPU 的问题首先需要获得系统的 CPU 信息。可以使用 GetProcessorInfo()获得多

处理器的信息,然后指定进程在哪一个处理器上运行。其中指定运行使用的是

SetThreadAffinityMask()函数。

另外,还可以使用 RDTSC 指令获取当前 CPU 核心运行周期数。

 x86 平台上定义函数:

 

 x64 平台上定义:

#define GetCPUTickCount() __rdtsc()

使用 CallNtPowerInformation API 得到 CPU 频率,从而将周期数转化为毫秒数,例如:

代码清单 1-5

_PROCESSOR_POWER_INFORMATION info;

CallNTPowerInformation(11, //query processor power information

   NULL,//no input buffer

   0,//input buffer size is zero

   &info,//output buffer

   Sizeof(info));//outbuf size

__int64 t_begin = GetCPUTickCount();

//do something

__int64 t_end = GetCPUTickCount();

double millisec = ((double)t_end –

   (double)t_begin)/(double)info.CurrentMhz;

RDTSC 指令读取当前 CPU 的周期数,在多 CPU 系统中,这个周期数在不同的 CPU 

间基数不同,频率也有可能不同。用从两个不同的 CPU 得到的周期数作计算会得出没有意

      线              CPU           

SetThreadAffinityMask 避免线程迁移。另外,CPU 的频率会随系统供电及负荷情况有所调整。

总结

能帮助你了解当前线程/进程/系统效能的 API 大致有以下这些:

1. Sleep()——这个方法能让当前线程下来。

2. WaitForSingleObject()——自己停下来,等待某个事件发生

3. GetTickCount()——有人把 Tick 翻译成嘀嗒,很形象。

4. QueryPerformanceFrequency()QueryPerformanceCounter()——让你访问到精

度更高的 CPU 数据。

5. timeGetSystemTime()——是另一个得到高精度时间的方法。

6. PerformanceCounter——效能计数器。

7. GetProcessorInfo()/SetThreadAffinityMask()遇到多核的问题怎么办呢?这两

个方法能够帮你更好地控制 CPU

8. GetCPUTickCount()。想拿到 CPU 核心运行周期数吗?用用这个方法吧。

了解并应用了上面的 API,就可以考虑在简历中写上精通 Windows”了。

 

 

 

以上摘自《编程之美——微软技术面试心得》 电子工业出版社