为了账号安全,请及时绑定邮箱和手机立即绑定

在 Golang 中以最小间隔调用具有可变执行时间的函数的最佳方法?

在 Golang 中以最小间隔调用具有可变执行时间的函数的最佳方法?

Go
至尊宝的传说 2023-06-05 17:16:49
我想在 Go 中以不少于给定时间间隔执行一个函数,以一次调用开始到下一次调用开始为衡量标准。函数本身的执行时间会有所不同。如果该函数运行的时间超过该间隔,我想立即再次运行它。但是如果/当它最终在不到一个完整的间隔内恢复完成时,我希望它立即恢复等待直到下一个间隔边界。对于上下文,这是一个速率限制器——被调用的函数可以很容易地让 CPU 旋转,但它不会产生额外的价值,因为它正在与不可能快速反应的人进行交互。为清楚起见的示例(interval == 20ms例如):runtime:  15mswait:      5msruntime:  25mswait:      0msruntime:  25mswait:      0msruntime:  15mswait:      5ms <-- this is the important bit如果我使用time.Ticker,我相信额外的“滴答”将在通道中排队Ticker.C(如果它被缓冲)导致它在恢复时立即进行一堆调用,或者 Ticker 的编写器将阻止写入通道并结束恢复后第一次调用的延迟过长。现在我正在做一些数学运算,这是有效的,但感觉它可能不符合惯用语:minDurationBetweenRuns := time.Millisecond * 100for {    lastRunTime := time.Now()    DO_STUFF_HERE()    durationSinceLastRun := time.Now().Sub(lastRunTime)    if durationSinceLastRun < minDurationBetweenRuns {        sleepTime := minDurationBetweenRuns - durationSinceLastRun        if sleepTime > minDurationBetweenRuns {            sleepTime = minDurationBetweenRuns        }        time.Sleep(sleepTime)    }}
查看完整描述

1 回答

?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

在写问题时,我记得 Golang 源代码非常容易阅读……并且认为我应该在看起来很傻之前先看一眼。我对我的发现很满意 :)

如果报价阅读器落后,它将开始丢弃报价,而不是阻塞写入通道(缓冲区只有 1)。这样做的效果是在我们错过一个或多个滴答时立即让事情回到“正轨”。

示例证明:

package main


import (

    "fmt"

    "time"

)


func main() {

    t := time.NewTicker(time.Millisecond * 50)

    for i := 0; i < 10; i++ {

        fmt.Printf("New invocation starting at %dms\n", time.Now().Round(time.Millisecond).Nanosecond()/int(time.Millisecond))

        if i%3 == 0 {

            fmt.Println("Executing for 25ms")

            time.Sleep(time.Millisecond * 25)

        } else {

            fmt.Println("Executing for 75ms")

            time.Sleep(time.Millisecond * 75)

        }

        fmt.Println("Waiting for ticker...")

        <-t.C

    }

    t.Stop()

}

输出:


New invocation starting at 0ms

Executing for 25ms

Waiting for ticker...

New invocation starting at 50ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 125ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 200ms

Executing for 25ms

Waiting for ticker...

New invocation starting at 250ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 325ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 400ms

Executing for 25ms

Waiting for ticker...

New invocation starting at 450ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 525ms

Executing for 75ms

Waiting for ticker...

New invocation starting at 600ms

Executing for 25ms

Waiting for ticker...


查看完整回答
反对 回复 2023-06-05
  • 1 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信