Go:time.Sleep的意外结果

huangapple go评论75阅读模式
英文:

Go: Unexpected Results from time.Sleep

问题

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

package main

import (
	"fmt"
	"time"
)

func main() {
	startTime := time.Now()
	for i := 0; i < 1000; i++ {
		time.Sleep(1 * time.Millisecond)
	}
	fmt.Printf("%d\n", 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("%d\n", time.Since(startTime).Milliseconds())
}

我得到的输出是:

15611

这实际上是相同的持续时间,即使睡眠持续时间应该是10倍长。这说明循环迭代和启动睡眠的开销不是14毫秒,因为如果是这样的话,总时间应该是(14+10)*1000 = 24000毫秒,但实际上并不是这样。

我漏掉了什么?为什么这段代码执行的时间相同,无论睡眠持续时间是1毫秒还是10毫秒?

请注意,我尝试在Go Playground中运行此代码,但结果不同;我认为它处理睡眠的方式不同。这些结果在我的笔记本电脑上是一致的,该笔记本电脑配有i7-10510处理器。

英文:

Running this code (as a built executable, not with the debugger):

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	startTime := time.Now()
	for i := 0; i &lt; 1000; i++ {
		time.Sleep(1 * time.Millisecond)
	}
	fmt.Printf(&quot;%d\n&quot;, time.Since(startTime).Milliseconds())
}

I get the output:

15467

This seems like a major overhead for calling the time.Sleep() function; it's essentially taking 15ms per loop iteration, even though it's only sleeping for 1ms in each loop. This suggests that there's a 14ms overhead for running an iteration of the loop and initiating a sleep.

If we adjust the sleep duration:

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	startTime := time.Now()
	for i := 0; i &lt; 1000; i++ {
		time.Sleep(10 * time.Millisecond)
	}
	fmt.Printf(&quot;%d\n&quot;, time.Since(startTime).Milliseconds())
}

I get the output:

15611

This is essentially the same duration, even though it should be sleeping for 10x as long. This kills the idea that there's a 14ms overhead for the loop iteration and initiating the sleep, because if that were the case, it would be (14+10)*1000 = 24000ms total, which it is not.

What am I missing? Why would this code take the same duration to execute, whether the sleep duration is 1ms or 10ms?

Note that I've tried running this in the Go playground but get different results; I think it handles sleeping differently. These results are consistent on my laptop, which is running an i7-10510.

答案1

得分: 2

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

例如,对于在x86处理器上运行的Windows,默认的系统时钟滴答间隔通常约为15毫秒,最小的系统时钟滴答间隔约为1毫秒。因此,默认分辨率计时器(如果未设置EX_TIMER_HIGH_RESOLUTION标志,则ExAllocateTimer创建的计时器)的到期时间只能在约15毫秒内控制,但高分辨率计时器的到期时间可以在1毫秒内控制。

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

以下是更多相关信息的线程:

英文:

It is probably related to the frequency of the system's timer. For example, on Windows the clock ticks every 15 milliseconds (source):

> For example, for Windows running on an x86 processor, the default interval between system clock ticks is typically about 15 milliseconds, and the minimum interval between system clock ticks is about 1 millisecond. Thus, the expiration time of a default-resolution timer (which ExAllocateTimer creates if the EX_TIMER_HIGH_RESOLUTION flag is not set) can be controlled only to within about 15 milliseconds, but the expiration time of a high-resolution timer can be controlled to within a millisecond.

If you need a higher precision timer you probably need to find a way to use High-Resolution Timers.

More information can be found in the threads below:

huangapple
  • 本文由 发表于 2022年8月17日 15:31:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/73384457.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定