【解法三】能动态适应的解法 |
代码清单 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 核心运行周期数。 |
在 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”了。 |
以上摘自《编程之美——微软技术面试心得》 电子工业出版社
转载于:https://blog.51cto.com/icbcchina/1180283