Go:来自时间的意外结果.睡觉



运行此代码(作为构建的可执行文件,而不是使用调试器(:

package main
import (
"fmt"
"time"
)
func main() {
startTime := time.Now()
for i := 0; i < 1000; i++ {
time.Sleep(1 * time.Millisecond)
}
fmt.Printf("%dn", time.Since(startTime).Milliseconds())
}

我得到输出:

15467

这似乎是调用time.Sleep()函数的主要开销;它基本上每次循环迭代需要15毫秒,尽管每次循环只睡1毫秒。这表明,运行循环的迭代和启动睡眠需要14毫秒的开销。

如果我们调整睡眠持续时间:

package main
import (
"fmt"
"time"
)
func main() {
startTime := time.Now()
for i := 0; i < 1000; i++ {
time.Sleep(10 * time.Millisecond)
}
fmt.Printf("%dn", time.Since(startTime).Milliseconds())
}

我得到输出:

15611

这基本上是相同的持续时间,即使它应该睡10倍的时间。这扼杀了循环迭代和启动睡眠需要14ms开销的想法,因为如果是这样的话,总开销将是(14+10(*1000=24000ms,但事实并非如此。

我错过了什么?为什么这个代码需要相同的持续时间才能执行,无论睡眠持续时间是1ms还是10ms?

请注意,我试过在围棋操场上跑这个,但得到了不同的结果;我认为它对睡眠的处理方式不同。这些结果在我运行i7-10510的笔记本电脑上是一致的。

这可能与系统计时器的频率有关。例如,在Windows上,时钟每15毫秒一次(来源(:

例如,对于运行在x86处理器上的Windows,系统时钟信号之间的默认间隔通常约为15毫秒,系统时钟脉冲之间的最小间隔约为1毫秒。因此,默认分辨率计时器(如果未设置EX_timer_HIGH_resolution标志,则ExAllocateTimer创建该计时器(的到期时间可以仅控制在大约15毫秒内,但是高分辨率计时器的到期时间可控制在一毫秒内。

如果您需要更高精度的计时器,您可能需要找到使用高分辨率计时器的方法。

更多信息可以在以下线程中找到:

  • https://github.com/golang/go/issues/44343https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
  • https://github.com/golang/go/issues/44343

最新更新