测量执行时间,如果在golang等待时间过长,请停止等待

测量执行时间,如果在golang等待时间过长,请停止等待,go,Go,我试图用unpredictiveExecutionTime测量函数的执行时间 func measureTime(expectedMs float64) (ok bool) { t1 := time.Now() funcWithUnpredictiveExecutionTime() t2 := time.Now() diff := t2.Sub(t1) 当funcWithUnpredictiveExecutionTime的工作速度比我预期的快时,测量就可以了。但是

我试图用unpredictiveExecutionTime测量
函数的执行时间

func measureTime(expectedMs float64) (ok bool) {
    t1 := time.Now()
    funcWithUnpredictiveExecutionTime()
    t2 := time.Now()
    diff := t2.Sub(t1)
funcWithUnpredictiveExecutionTime
的工作速度比我预期的快时,测量就可以了。但是,如果其工作速度低于
expectedMs
,则测量不会在预期的毫秒数之后立即停止

funcWithUnpredictiveExecutionTime
的工作时间超过
expectedMs
时,是否可以停止时间测量,而不等待
funcWithUnpredictiveExecutionTime
完成

换句话说,
measureTime(200)
应该在
200ms
内返回,无论结果是好是坏

我想我应该使用频道,然后以某种方式取消等待频道。但具体怎么做呢

完整代码:

package main

import (
    "fmt"
    "math/rand"
    "time"
)

// random number between min and max
func random(min, max int) int {
    rand.Seed(time.Now().Unix())
    return rand.Intn(max-min) + min
}

// sleeps for a random milliseconds amount between 200 and 1000
func funcWithUnpredictiveExecutionTime() {
    millisToSleep := random(200, 1000)
    fmt.Println(fmt.Sprintf("Sleeping for %d milliseconds", millisToSleep))
    time.Sleep(time.Millisecond * time.Duration(millisToSleep))
}

// measures execution time of a function funcWithUnpredictiveExecutionTime
// if expectedMs < actual execution time, it's ok.
// if expectedMs milliseconds passed and funcWithUnpredictiveExecutionTime
// still did not finish execution it should return
// without waiting for funcWithUnpredictiveExecutionTime
func measureTime(expectedMs float64) (ok bool) {
    t1 := time.Now()
    funcWithUnpredictiveExecutionTime()
    t2 := time.Now()
    diff := t2.Sub(t1)
    actualMs := diff.Seconds() * 1000
    ok = actualMs < expectedMs
    fmt.Println(actualMs)
    return
}

// prints results: Ok or too late
func printTimeResults(ok bool) {
    if ok {
        fmt.Println("Ok")
    } else {
        fmt.Println("Too late")
    }
}

func main() {
    printTimeResults(measureTime(200))  // expect it to finish in 200 ms anyway
    printTimeResults(measureTime(1000)) // expect it to finish in 1000 ms anyway
}

您不能取消goroutine,除非您将其设计为取消。您可以通过使用一个通道发出信号,表示正在计时的功能已完成,从而使计时功能短路:

func measureTime(expectedMs float64) (ok bool) {
    done := make(chan struct{})
    t1 := time.Now()

    go func() {
        funcWithUnpredictiveExecutionTime()
        close(done)
    }()

    select {
    case <-done:
        ok = true
    case <-time.After(time.Duration(expectedMs) * time.Millisecond):
    }

    fmt.Println(time.Since(t1))
    return ok

}
func measureTime(expectedMs float64)(ok bool){
完成:=make(chan结构{})
t1:=时间。现在()
go func(){
funcWithUnpredictiveExecutionTime()
结束(完成)
}()
挑选{

case用我个人为异步后台工作人员遵循的设计稍微扩展一下JimB的示例。我要说的是,在大多数情况下,在不传递中止通道的情况下启动go例程是不可接受的……所有异步方法都应该接受一个作为参数,或者在其接收类型上定义一个,这样您就可以实际控制exEuction.仅供参考,这里有一个简单的图书馆,是我的一位老同事制作的

如果您的程序没有针对每个goroutine的中止路径,您可能迟早会面临重大的质量问题。此外,对于在goroutine中执行繁重任务的应用程序,您可能无法正常地停止和启动应用程序

func measureTime(expectedMs float64) (ok bool) {
    done := make(chan struct{})
    abort := make(chan struct{})
    t1 := time.Now()

    go func() {
        funcWithUnpredictiveExecutionTime(abort)
        close(done)
    }()

    select {
    case <-done:
        ok = true
    case <-time.After(time.Duration(expectedMs) * time.Millisecond):
        // after signals here when the duration is reached so I close abort
        close(abort)
    }

    fmt.Println(time.Since(t1))
    return ok

}


funcWithUnpredictiveExecutionTime(abort) {
     for {
        select {
           // doing work in here
           case abort:
              // except here, we clean up and return
        }
     }
}
func measureTime(expectedMs float64)(ok bool){
完成:=make(chan结构{})
中止:=make(chan结构{})
t1:=时间。现在()
go func(){
funcWithUnpredictiveExecutionTime(中止)
结束(完成)
}()
挑选{

案例如您所述,可以停止等待,但不能终止goroutine。如果您确实希望func停止,则必须让func检查退出信号(或者,如果它正在进行网络调用,则设置读/写超时)。与您的问题无关:不要重新为PRNG设定种子。种子设定通常只执行一次(除非您明确希望/需要从其他种子重新启动随机数序列)。特别是,由于您选择使用
time.Now().Unix()
您的“random”函数将始终返回完全相同的值,直到您的时钟跳到新的一秒!(我只需使用
func init(){rand.seed(time.Now().UnixNano())}
在主程序包中,或将该行放入
main
本身)。这真的保证计时器会立即停止吗?@DenysSéguret:它保证
measureTime
会立即停止。你不能用unpredictiveExecutionTime
停止
funcy。它在没有任何类型的取消api的情况下处于阻塞状态,因此它必须运行到完成。你确定
funcWithUn时有这种保证吗predictiveExecutionTime
并不能减轻CPU的负担?你能在操场上演示一下吗?@DenysSéguret:Go确实有一个大部分是抢占式的调度器,它支持
GOMAXPROCS>1
。但是,如果你在繁忙循环中运行的函数比线程多,那么它会导致问题。不过,这更多是一个实现细节,具体取决于DenysSéguret——这应该符合JimB声称的()。如果您确信它不会,您可以构建一个程序来显示它。否则,询问者可能会尝试并以这种方式进行排序。
func measureTime(expectedMs float64) (ok bool) {
    done := make(chan struct{})
    abort := make(chan struct{})
    t1 := time.Now()

    go func() {
        funcWithUnpredictiveExecutionTime(abort)
        close(done)
    }()

    select {
    case <-done:
        ok = true
    case <-time.After(time.Duration(expectedMs) * time.Millisecond):
        // after signals here when the duration is reached so I close abort
        close(abort)
    }

    fmt.Println(time.Since(t1))
    return ok

}


funcWithUnpredictiveExecutionTime(abort) {
     for {
        select {
           // doing work in here
           case abort:
              // except here, we clean up and return
        }
     }
}