Golang中如何测量代码执行时间
Golang中如何测量代码执行时间
package main
import (
"time"
)
func main() {
start := time.Now()
ch := make(chan int)
go func() {
for i := 0; i < 100; i++ {
ch <- i
}
}()
go chanReader(ch, "JHON")
go chanReader(ch, "DOE")
elapsed := time.Since(start)
println(elapsed)
}
func chanReader(ch chan int, name string) {
for v := range ch {
println(v, " FROM ", name)
time.Sleep(time.Millisecond * 5)
}
}
如何测量执行时间?我知道可以使用 start := time.Now() 和 elapsed := time.Since(start),但如果我添加这些代码,主线程会在两个chanReader完成之前结束执行。我还尝试添加var wg sync.WaitGroup但出现了死锁,不知道是什么原因。我想计算使用fun out模式是否更好。
更多关于Golang中如何测量代码执行时间的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你对 WaitGroup 的使用可能不正确。你肯定需要一种方式让工作线程向主例程传递完成或结束信号。只有在接收到信号后,你才能记录完成时间。
更多关于Golang中如何测量代码执行时间的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你关于WaitGroup的想法是正确的,我假设你已经正确实现了它。但即使正确实现了WaitGroup,你也需要终止chanReader()函数中的for-range循环来避免死锁。如果ch通道保持打开状态,for v := range ch循环将永远不知道何时停止请求数据。
要解决这个问题,你需要在发送完所有必需数据后关闭ch通道。以下是我的实现方式:
package main
import (
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
start := time.Now()
ch := make(chan int)
go func() {
for i := 0; i < 100; i++ {
ch <- i
}
// 注意我在这里关闭了通道
// 这让接收者知道没有更多数据要发送了
close(ch)
}()
wg.Add(2)
go chanReader(ch, "JOHN")
go chanReader(ch, "DOE")
wg.Wait()
elapsed := time.Since(start)
println(elapsed)
}
func chanReader(ch chan int, name string) {
defer wg.Done()
for v := range ch {
println(v, " FROM ", name)
time.Sleep(time.Millisecond * 5)
}
}
在Go语言中,测量并发代码执行时间的关键是确保所有goroutine都完成后再计算总时间。你的代码中主goroutine在启动其他goroutine后立即结束,导致测量不准确。
以下是修正后的代码:
package main
import (
"sync"
"time"
)
func main() {
start := time.Now()
ch := make(chan int)
var wg sync.WaitGroup
// 启动生产者goroutine
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
ch <- i
}
close(ch) // 关闭channel以通知读取者结束
}()
// 启动两个消费者goroutine
wg.Add(2)
go chanReader(ch, "JHON", &wg)
go chanReader(ch, "DOE", &wg)
// 等待所有goroutine完成
wg.Wait()
elapsed := time.Since(start)
println("Total execution time:", elapsed.String())
}
func chanReader(ch chan int, name string, wg *sync.WaitGroup) {
defer wg.Done()
for v := range ch {
println(v, " FROM ", name)
time.Sleep(time.Millisecond * 5)
}
}
关键修改点:
- 使用
sync.WaitGroup来等待所有goroutine完成 - 在生产goroutine中关闭channel,这样读取goroutine的
range循环会在channel关闭后自动退出 - 在
chanReader函数中调用wg.Done()来通知WaitGroup任务完成
关于fan-out模式的性能对比,你可以这样测试:
// 单消费者版本用于对比
func singleReaderBenchmark() {
start := time.Now()
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
ch <- i
}
close(ch)
}()
wg.Add(1)
go func() {
defer wg.Done()
for v := range ch {
println(v, " FROM ", "SINGLE_READER")
time.Sleep(time.Millisecond * 5)
}
}()
wg.Wait()
elapsed := time.Since(start)
println("Single reader time:", elapsed.String())
}
通过比较两种模式的执行时间,你可以确定在特定场景下哪种模式性能更好。

