为什么 Sleep() 会减慢后续代码 40 毫秒? [英] Why does Sleep() slow down subsequent code for 40ms?

查看:97
本文介绍了为什么 Sleep() 会减慢后续代码 40 毫秒?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最初是在 coderanch.com 上询问这个问题的,所以如果你试图在那里帮助我,谢谢,并且不要觉得有必要重复这项工作.不过,coderanch.com 主要是一个 Java 社区,这似乎(经过一些研究)确实是一个 Windows 问题,所以我和那里的同事认为这可能是寻求帮助的更合适的地方.

I originally asked about this at coderanch.com, so if you've tried to assist me there, thanks, and don't feel obliged to repeat the effort. coderanch.com is mostly a Java community, though, and this appears (after some research) to really be a Windows question, so my colleagues there and I thought this might be a more appropriate place to look for help.

我编写了一个简短的程序,它要么在 Windows 性能计数器上旋转直到 33 毫秒过去,要么调用 Sleep(33).前者没有表现出意外的影响,但后者似乎(不一致地)将后续处理减慢了大约 40 毫秒(或者,或者它对性能计数器返回的值有一些影响).在自旋或 Sleep() 之后,程序调用一个例程 runInPlace(),它自旋 2 毫秒,计算它查询性能计数器的次数,并返回该数字.

I have written a short program that either spins on the Windows performance counter until 33ms have passed, or else calls Sleep(33). The former exhibits no unexpected effects, but the latter appears to (inconsistently) slow subsequent processing for about 40ms (either that, or it has some effect on the values returned from the performance counter for that long). After the spin or Sleep(), the program calls a routine, runInPlace(), that spins for 2ms, counting the number of times it queries the performance counter, and returning that number.

当最初的 33 毫秒延迟是通过旋转完成时,runInPlace() 的迭代次数往往是(在我的 Windows 10,XPS-8700 上)大约 250,000.它会有所不同,可能是由于其他系统开销,但它会在 250,000 左右平滑变化.

When the initial 33ms delay is done by spinning, the number of iterations of runInPlace() tends to be (on my Windows 10, XPS-8700) about 250,000. It varies, probably due to other system overhead, but it varies smoothing around 250,000.

现在,当通过调用 Sleep() 完成初始延迟时,会发生一些奇怪的事情.许多对 runInPlace() 的调用返回一个接近 250,000 的数字,但其中相当多的调用返回一个接近 50,000 的数字.同样,范围在 50,000 左右变化,相当平稳.但是,它显然是取两者的平均值,在 80,000 到 150,000 之间几乎没有任何回报.如果我在每次延迟后调用 runInPlace() 100 次,而不是只调用一次,则在第 20 次调用后它永远不会返回较小范围内的迭代次数.当 runInPlace() 运行 2 毫秒时,这意味着我观察到的行为在 40 毫秒后消失.如果我让 runInPlace() 运行了 4 毫秒而不是 2 毫秒,它在第 10 次调用后永远不会返回较小范围内的迭代次数,因此,再次,该行为在 40 毫秒后消失(同样,如果 runInPlace() 仅运行了 1 毫秒;该行为在第 40 次调用后消失).

Now, when the initial delay is done by calling Sleep(), something strange happens. A lot of the calls to runInPlace() return a number near 250,000, but quite a few of them return a number near 50,000. Again, the range varies around 50,000, fairly smoothly. But, it is clearly averaging one or the other, with nearly no returns anywhere between 80,000 and 150,000. If I call runInPlace() 100 times after each delay, instead of just once, it never returns a number of iterations in the smaller range after the 20th call. As runInPlace() runs for 2ms, this means the behavior I'm observing disappears after 40ms. If I have runInPlace() run for 4ms instead of 2ms, it never returns a number of iterations in the smaller range after the 10th call, so, again, the behavior disappears after 40ms (likewise if have runInPlace() run for only 1ms; the behavior disappears after the 40th call).

这是我的代码:

#include "stdafx.h"
#include "Windows.h"

int runInPlace(int msDelay)
{
    LARGE_INTEGER t0, t1;
    int n = 0;

    QueryPerformanceCounter(&t0);

    do
    {
            QueryPerformanceCounter(&t1);
            n++;
    } while (t1.QuadPart - t0.QuadPart < msDelay);

    return n;
}

int _tmain(int argc, _TCHAR* argv[])
{
    LARGE_INTEGER t0, t1;
    LARGE_INTEGER frequency;
    int n;

    QueryPerformanceFrequency(&frequency);

    int msDelay = 2 * frequency.QuadPart / 1000;

    int spinDelay = 33 * frequency.QuadPart / 1000;

    for (int i = 0; i < 100; i++)
    {
        if (argc > 1)
            Sleep(33);
        else
        {
            QueryPerformanceCounter(&t0);

            do
            {
                    QueryPerformanceCounter(&t1);
            } while (t1.QuadPart - t0.QuadPart < spinDelay);
        }

        n = runInPlace(msDelay);
        printf("%d \n", n);
    }

    getchar();

    return 0;
}

以下是我在使用 Sleep() 延迟时得到的一些典型输出:

Here's some output typical of what I get when using Sleep() for the delay:

561162489365365934311233488549214790445765314545563355870556073236321981021140021635827403924463515228215177943057374422516585381356237259858252275251099

56116 248936 53659 34311 233488 54921 47904 45765 31454 55633 55870 55607 32363 219810 211400 216358 274039 244635 152282 151779 43057 37442 251658 53813 56237 259858 252275 251099

这是我旋转以创建延迟时得到的一些典型输出:

And here's some output typical of what I get when I spin to create the delay:

276461280869276215280850188066280666281139280904277886279250244671240599279697280844159246271938263632260892238902255570265652274005273604150640279153281146280845248277

276461 280869 276215 280850 188066 280666 281139 280904 277886 279250 244671 240599 279697 280844 159246 271938 263632 260892 238902 255570 265652 274005 273604 150640 279153 281146 280845 248277

谁能帮我理解这种行为?(请注意,我已经在五台计算机上尝试过使用 Visual C++ 2010 Express 编译的这个程序.它只在我拥有的两台最快的机器上显示了这种行为.)

Can anyone help me understand this behavior? (Note, I have tried this program, compiled with Visual C++ 2010 Express, on five computers. It only shows this behavior on the two fastest machines I have.)

推荐答案

这听起来像是由于降低了 CPU 在计算机不忙时运行的时钟速度 (SpeedStep).当计算机空闲时(如处于睡眠状态),时钟速度将下降以减少功耗.在较新的 CPU 上,这可能是所列时钟速度的 35% 或更少.一旦计算机再次忙碌,在 CPU 再次加速之前会有一小段延迟.

This sounds like it is due to the reduced clock speed that the CPU will run at when the computer is not busy (SpeedStep). When the computer is idle (like in a sleep) the clock speed will drop to reduce power consumption. On newer CPUs this can be 35% or less of the listed clock speed. Once the computer gets busy again there is a small delay before the CPU will speed up again.

您可以关闭此功能(在 BIOS 中或通过将电源计划高级设置中处理器电源管理"下的最低处理器状态"设置更改为 100%.

You can turn off this feature (either in the BIOS or by changing the "Minimum processor state" setting under "Processor power management" in the advanced settings of your power plan to 100%.

这篇关于为什么 Sleep() 会减慢后续代码 40 毫秒?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆