首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >time.Ticker的性能

time.Ticker的性能
EN

Stack Overflow用户
提问于 2021-07-02 14:10:46
回答 1查看 223关注 0票数 2

不能找出在下面的for循环中的哪里,我们花费了超过10微秒,所以我们错过了大量的滴答?

代码语言:javascript
复制
package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    RunTicker(time.Millisecond, 10 * time.Second) // Scenario 1
    RunTicker(10 * time.Microsecond, 10 * time.Second) // Scenario 2
}

func RunTicker(tickerInterval, tickerDuration time.Duration) {
    var counter int

    ctx, can := context.WithTimeout(context.Background(), tickerDuration)
    defer can()

    ticker := time.NewTicker(tickerInterval)

exitfor:
    for {
        select {
        case <-ticker.C:
            counter++
        case <- ctx.Done():
            ticker.Stop()
            break exitfor
        }
    }

    fmt.Printf("Tick interval %v and running for %v.Expected counter: %d but got %d\n", tickerInterval, tickerDuration, tickerDuration/tickerInterval, counter)
}

输出:

代码语言:javascript
复制
Tick interval 1ms and running for 10s.Expected counter: 10000 but got 9965
Tick interval 10µs and running for 10s.Expected counter: 1000000 but got 976590
EN

回答 1

Stack Overflow用户

发布于 2021-07-02 15:10:27

一般来说,当API说一个事件需要X秒时,它实际上是在保证运行时间至少是X秒,而不是更少。特别是对于小的时间增量,这是一个重要的区别。

此外,请从NewTicker documentation考虑这一点

持续时间由持续时间参数指定。报价器将调整时间间隔或丢弃报时,以弥补速度慢的接收器。

考虑到这两点,您真正拥有的唯一保证是实际滴答的数量将<=到您计算的预期数量,而且不会更多。换句话说,实际滴答和预期滴答仅在理想情况下中,并且每隔一段时间都会小于该值。

在这种小的时间增量(~< 1ms)中,除了“用户代码”之外,还可能有其他事件超过滴答时间,包括:

  • Goroutine调度逻辑(休眠和恢复Goroutine,线程switching).
  • Garbage收集(即使在循环期间没有产生垃圾,GC可能仍然是“活动的”,并且偶尔会检查垃圾)

这些其他因素可能会同时出现,使得计时更有可能被跳过或延迟。

想象一下,你有一个装满水的水桶,你需要把它倒入另一个水桶,然后是另一个水桶,然后是另一个水桶,以此类推,以容纳1000个水桶。你唯一能做的就是失去水,一旦它溢出了,你就再也得不到了。在这种情况下,您永远不会期望将100%的水保留到最后。

这与您提到的情况类似,因为错误只在一个方向上。延迟只能至少是指定的时间,并且计时只能丢失(永远不会获得额外的时间)。每当这些事件发生时,就像是失去了一滴水。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68220364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档