如何测量并发函数的执行时间?

huangapple go评论72阅读模式
英文:

How to measure execution time of concurrent functions?

问题

我有一个使用goroutine执行的for循环。以下是代码片段的样子:

var wg sync.WaitGroup
for _, photo := range photos {
    wg.Add(1)
    
    go func() {
        defer wg.Done()
        start := time.Now()
        
        result := process(photo)
        
        fmt.Println("took %s", time.Since(start))
    }()
}

go func() {
    wg.Wait()
}()

在上述代码中,我想要计算每个process(photo)函数的执行时间。但是我目前的做法似乎是错误的。我得到的数字不是真实的。请问我哪里出错了,如何修复它?

英文:

I have for loop which executes goroutine. Here is the piece of code how it looks:

var wg sync.WaitGroup
for _, photo := range photos {
	    wg.Add(1)
		
        go func() {
			defer wg.Done()
			start := time.Now()
			
			result := process(photo)
			
			fmt.Println("took %s", time.Since(start))
		}()
	}
	
	go func() {
		wg.Wait()
	}()

In the above code, I want to count execution time of each process(photo) function. But the way I do it seems wrong. The numbers I get is not real. Where is my mistake and how to fix it?

答案1

得分: 2

与其根据要处理的图片数量创建大量的goroutine,不如根据CPU核心数创建相同数量的goroutine,这样可以避免资源的浪费和系统资源的耗尽。将每个空闲的goroutine分配一张图片,并在其处理图片时计时。当图片处理完成并停止计时器后,记录时间并将另一张图片交给该goroutine进行处理。这样就不会有等待调度且占用内存的goroutine。

参考链接:https://gobyexample.com/worker-pools

英文:

Instead of creating as many goroutines as you have pictures to process you would be better off creating as many goroutines as you have CPU cores so that there is no wasteful usage or exhaustion of system resources. Hand out one picture to every idle goroutine and make time it while it processes the picture. When picture processing is over and you stopped the timer, log the time and hand that goroutine another picture to process. No goroutines waiting to be scheduled that consume memory.

See https://gobyexample.com/worker-pools for a starting point.

答案2

得分: 1

你需要将photo变量传递给你的go协程,或者在for循环内部引入一个局部变量,并将该变量传递给process()函数,否则所有的go协程将共享同一个photo变量的实例。

另外,在另一个go协程中写入wg.Wait()没有意义。你可以像这样更新你的代码:

var wg sync.WaitGroup
for _, photo := range photos {
        wg.Add(1)

        photo := photo

        go func() {
            defer wg.Done()
            start := time.Now()
            
            result := process(photo)
            
            fmt.Println("took %s", time.Since(start))
        }()
  }
  wg.Wait()
英文:

You need to pass the photo variable to your go-routine or introduce a local variable inside the for loop and pass that variable to process() function, otherwise all your go-routines will have the same instance of photo variable.

And, there is no point writing wg.Wait() in another go-routine. You can updated your code like this

var wg sync.WaitGroup
for _, photo := range photos {
        wg.Add(1)

        photo := photo

        go func() {
            defer wg.Done()
            start := time.Now()
            
            result := process(photo)
            
            fmt.Println("took %s", time.Since(start))
        }()
  }
  wg.Wait()

huangapple
  • 本文由 发表于 2022年8月15日 11:55:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/73356773.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定