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