Sleep in golang causes a tenfold difference in time interval

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

Sleep in golang causes a tenfold difference in time interval

问题

我在项目中进行压力测试时发现由于time.Sleep引起的时间间隔存在较大差异,我将其抽象为以下代码:

代码1:

func TestSleep(t *testing.T) {
    for i := 0; i < 8; i++ {
        //time.Sleep(time.Second)
        t1 := time.Now()
        fmt.Println(time.Since(t1))
    }
}

输出:

229ns
37ns
36ns
37ns
36ns
38ns
37ns
39ns

代码2(添加time.Sleep):

func TestSleep(t *testing.T) {
    for i := 0; i < 8; i++ {
        time.Sleep(time.Second)
        t1 := time.Now()
        fmt.Println(time.Since(t1))
    }
}

输出:

471ns
267ns
855ns
484ns
359ns
296ns
324ns
302ns

我有两个问题:

  1. 为什么两个结果之间存在如此大的差异(仅time.Sleep的差异)?
  2. 为什么代码1的第一个输出要比后面的输出大得多?
英文:

I was doing pressure testing in my project and found a large gap in the time interval due to time.Sleep, which I abstracted to the following code:
code 1:

func TestSleep(t *testing.T) {
	for i := 0; i &lt; 8; i++ {
		//time.Sleep(time.Second)
		t1 := time.Now()
		fmt.Println( time.Since(t1))
	}
}

output:

229ns
37ns
36ns
37ns
36ns
38ns
37ns
39ns

code 2(add time.Sleep):

func TestSleep(t *testing.T) {
	for i := 0; i &lt; 8; i++ {
		time.Sleep(time.Second)
		t1 := time.Now()
		fmt.Println( time.Since(t1))
	}
}
471ns
267ns
855ns
484ns
359ns
296ns
324ns
302ns

I have two questions:

  1. Why is there such a big difference between the two results (only the time.Sleep difference)?
  2. Why is the first output in code1 much larger than the next?

答案1

得分: 1

正如mna在“Go中的睡眠和选择行为”中提到的,

> time.Sleep实际上是在运行时定义的:
>
> 从回顾来看,这是有道理的,因为它必须与goroutine调度器交互。
>
> 它最终调用goparkunlock,它“将goroutine置于等待状态”。
>
> time.Sleep创建一个带有回调函数的runtime.timer,当计时器到期时调用该回调函数-该回调函数通过调用goready唤醒goroutine。有关runtime.timer的更多详细信息,请参见下一节。

您可以在Vincent Blanchon的“Go:g0,特殊的Goroutine”中了解有关停车的更多信息。

> 接收消息的goroutine将切换到g0,并通过将其放入本地队列来解锁停放的goroutine:

Sleep in golang causes a tenfold difference in time interval

正如JimB所评论的那样,所有这些操作都需要时间。

英文:

As mentioned in "Behavior of sleep and select in go" by mna,

> time.Sleep is actually defined in the runtime:
>
> Which in retrospect makes a lot of sense, as it has to interact with the goroutine scheduler.
>
> It ends up calling goparkunlock, which "puts the goroutine into a waiting state".
>
> time.Sleep creates a runtime.timer with a callback function that is called when the timer expires - that callback function wakes up the goroutine by calling goready. See next section for more details on the runtime.timer.

You can see more about parking in "Go: g0, Special Goroutine" from Vincent Blanchon

> The goroutine receiving the message will switch to g0 and unlock the parked goroutine by putting it on the local queue:

Sleep in golang causes a tenfold difference in time interval

All those operation takes time, as JimB commented.

huangapple
  • 本文由 发表于 2021年11月4日 21:29:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/69840024.html
匿名

发表评论

匿名网友

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

确定