英文:
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
我有两个问题:
- 为什么两个结果之间存在如此大的差异(仅time.Sleep的差异)?
- 为什么代码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 < 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 < 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:
- Why is there such a big difference between the two results (only the time.Sleep difference)?
- 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:
正如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:
All those operation takes time, as JimB commented.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论