我正在尝试在 Go 中运行一个函数的基准测试,如果更多的 goroutine 同时调用它,我怀疑它会减慢速度。我想在基准测试期间捕获函数调用的 P50 和 P95 延迟,例如,使用 ,github.com/influxdata/tdigest如下所示:package mainimport ( "fmt" "math/rand" "sync" "testing" "time" "github.com/influxdata/tdigest")func BenchmarkSomething(b *testing.B) { concurrencies := []int{1, 10, 30} total := 1000 for _, concurrency := range concurrencies { b.Run(fmt.Sprintf("concurrency_%d", concurrency), func(b *testing.B) { td := tdigest.New() for i := 0; i < b.N; i++ { send := make(chan struct{}, total) var wg sync.WaitGroup for i := 0; i < concurrency; i++ { wg.Add(1) go func() { for range send { start := time.Now() duration := time.Duration(int64(rand.NormFloat64()*1e6)) + time.Millisecond time.Sleep(time.Duration(duration)) td.Add(float64(time.Since(start)), 1) } }() } for i := 0; i < total; i++ { send <- struct{}{} } close(send) } b.Log("P50 latency:", td.Quantile(0.50)) }) }}但是,如果我尝试运行它,我会收到一个index out of range错误:> go test -bench .goos: darwingoarch: amd64pkg: github.com/kurtpeek/send-closed-channelBenchmarkSomething/concurrency_1-8 panic: runtime error: index out of range我怀疑从多个 goroutine 调用这个函数是不安全的?有没有办法获得线程安全的估计器?
1 回答
慕桂英546537
TA贡献1848条经验 获得超10个赞
在高层次上,我通过将问题分为两个步骤来解决这个问题:将延迟发送到缓冲通道(在这种情况下,所需的缓冲区大小是预先知道的),然后调用td.Add()结果。这避免了并发调用td.Add(),同时仍然实现了在并发设置中测量延迟的预期结果。
- 1 回答
- 0 关注
- 148 浏览
添加回答
举报
0/150
提交
取消
