有人可以用Sleep(1)解释这个有趣的行为吗?

时间:2010-04-14 14:35:09

标签: c++ winapi

我正在测试各种win32 API调用在被要求等待1ms时等待多长时间。我试过了:

::睡眠(1)
:: WaitForSingleObject(handle,1)
:: GetQueuedCompletionStatus(句柄,&字节,&键,&重叠,1)

我使用QueryPerformanceCounter和QueryPerformanceFrequency检测已用时间。在大多数情况下,经过的时间大约是15毫秒,这在整个互联网上是预期和记录的。然而,在短时间内等待大约需要2ms !!!它持续发生几分钟,但现在又回到了15ms。我没有使用timeBeginPeriod()和timeEndPeriod调用!然后我在另一台机器上尝试了相同的应用程序,并等待持续约2ms!两台机器都有Windows XP SP2,硬件应该完全相同。有没有什么可以解释为什么等待时间变化如此之大? TIA

5 个答案:

答案 0 :(得分:4)

Thread.Sleep(0)将允许任何具有相同优先级的线程执行。 Thread.Sleep(1)将允许执行相同或更低优先级的任何线程。

在调度程序允许另一个线程执行之前,每个线程都有一个执行时间间隔。正如Billy ONeal所说,调用Thread.Sleep将把剩余的这个间隔放弃到其他线程(取决于上面的优先级考虑)。

Windows平衡整个操作系统上的线程 - 不仅仅是在您的进程中。这意味着操作系统上的其他线程也可以导致您的线程被抢占(即中断,并将剩余的时间间隔提供给另一个线程)。

有一篇文章可能对Thread.Sleep(x)主题感兴趣:

Priority-induced starvation: Why Sleep(1) is better than Sleep(0) and the Windows balance set manager

答案 1 :(得分:3)

更改计时器的分辨率可以通过系统上的任何进程完成,并且可以全局查看效果。 See this article关于Hotspot Java编译器如何处理Windows上的时间,特别是:

  

请注意,任何应用程序都可以更改定时器中断,并且它会影响整个系统。 Windows仅允许缩短时间段,从而确保所有应用程序的最短请求时间段是使用的时间段。如果进程未重置该时间段,则Windows将在进程终止时进行处理。虚拟机在启动时不会随意改变中断速率的原因 - 它可以做到这一点 - 是因为中断增加了10倍,对系统中的所有内容都有潜在的性能影响。然而,其他应用程序确实会改变它,通常是多媒体观众/播放器。

答案 2 :(得分:1)

sleep(1)做的最大的事情就是放弃线程的其余部分。这完全取决于当你致电sleep时你的线程的量子有多少。

答案 3 :(得分:1)

汇总之前所说的内容:

CPU时间以量子分配(时间片)
线程调度程序选择要运行的线程。即使优先级较高的线程准备好运行,该线程也可以在整个时间片上运行。

典型的时间片为8..15ms,具体取决于架构。

线程可以“放弃”时间片 - 通常是睡眠(0)或睡眠(1)。 Sleep(0)允许另一个具有相同或hogher优先级的线程运行下一个时间片。睡眠(1)允许“任何”线程。

时间片是全局的,可能会受到所有进程的影响
即使你没有改变时间片,别人也可以。

即使时间片没有改变,你也可以在两个不同时间之间“跳跃”。

为简单起见,假设一个核心,你的线程和另一个线程X。

如果线程X以与您相同的优先级运行,处理数字,则您的睡眠(1)将花费整个时间片,在客户端系统上通常为15毫秒。

如果线程X以较低的优先级运行,并在4 ms后放弃自己的时间片,则Sleep(1)将花费4 ms。

答案 4 :(得分:0)

我会说它只取决于cpu的加载方式,如果还有很多其他进程/线程可以更快地返回调用线程。