1.数据结构:源码位置:src/testing/benchmark.go:Btype B struct { common importPath string // import path of the package containing the benchmark bstate *benchState N int previousN int // number of iterations in the previous run previousDuration time.Duration // total duration of the previous run benchFunc func(b *B) benchTime durationOrCountFlag bytes int64 missingBytes bool // one of the subbenchmarks does not have bytes set. timerOn bool showAllocResult bool result BenchmarkResult parallelism int // RunParallel creates parallelism*GOMAXPROCS goroutines // The initial states of memStats.Mallocs and memStats.TotalAlloc. startAllocs uint64 startBytes uint64 // The net total of this test after being run. netAllocs uint64 netBytes uint64 // Extra metrics collected by ReportMetric. extra map[string]float64 // For Loop() to be executed in benchFunc. // Loop() has its own control logic that skips the loop scaling. // See issue #61515. loopN int }1).基础标识与调度:importPath:包导入路径.bstate:状态测试管理器.benchFunc:测试函数.2).循环控制:N:循环执行次数.previousN:上一轮循环次数.loopN:loop专用循环数.3).耗时统计:benchTime:测试目标耗时. 控制基准测试的最小总耗时默认 1s可通过-benchtime调整如-benchtime5s或-benchtime100x)previousDuration:上一轮总耗时.timerOn:计时器开关.4).内存或字节统计:bytes:每次迭代处理的字节数.missingBytes:测试字节数缺失标记.startAllocs:内存分布次数初始值.startBytes:内存分配字节初始值.netAllocs:总分配次数.netBytes:总分配字节数.5).并行控制:parallelism:并行度.6).结果与输出:result:基准测试结果.showAllocResult:内存结果显示标记.extra:自定义指标.7).通用能力:common:通用测试能力.2.启动计时.B.StartTimer():源码位置:src/testing/benchmark.gofunc (b *B) StartTimer() { if !b.timerOn { runtime.ReadMemStats(memStats) b.startAllocs memStats.Mallocs b.startBytes memStats.TotalAlloc b.start highPrecisionTimeNow() b.timerOn true } }StartTimer()负责启动计时并初始化内存相关计数.测试执行时会自动调用.一般不需要用户启动.流程图:3.停止计时.B.StopTimer():源码位置:src/testing/benchmark.goStopTimer()负责停止计时.并累加相应的值.// StopTimer stops timing a test. This can be used to pause the timer // while performing steps that you dont want to measure. func (b *B) StopTimer() { if b.timerOn { b.duration highPrecisionTimeSince(b.start) runtime.ReadMemStats(memStats) b.netAllocs memStats.Mallocs - b.startAllocs b.netBytes memStats.TotalAlloc - b.startBytes b.timerOn false } }需要注意的是.StopTimer()并不一定是测试结束.一个测试中有可能有多个统计阶段.所以统计值是累加的.流程图:4.重置计时.B.ResetTimer():ResetTimer()用于重置计时器.相应的也会把其他统计值也重置.源码位置:src/testing/benchmark.go// ResetTimer zeroes the elapsed benchmark time and memory allocation counters // and deletes user-reported metrics. // It does not affect whether the timer is running. func (b *B) ResetTimer() { if b.extra nil { // Allocate the extra map before reading memory stats. // Pre-size it to make more allocation unlikely. b.extra make(map[string]float64, 16) } else { clear(b.extra) } if b.timerOn { runtime.ReadMemStats(memStats) b.startAllocs memStats.Mallocs b.startBytes memStats.TotalAlloc b.start highPrecisionTimeNow() } b.duration 0 b.netAllocs 0 b.netBytes 0 }流程图:5.SetBytes():源码位置:src/testing/benchmark.go// SetBytes records the number of bytes processed in a single operation. // If this is called, the benchmark will report ns/op and MB/s. func (b *B) SetBytes(n int64) { b.bytes n }流程图:核心公式:// 总处理字节数 单次迭代字节数 × 总迭代次数totalBytes b.bytes × b.N// 总耗时秒 总有效耗时纳秒 / 10^9totalSeconds b.duration / 1e9// 吞吐量MB/s 总处理字节数MB / 总耗时秒// 注1MB 1024×1024 1048576 字节throughputMBps (totalBytes / 1048576) / totalSeconds测试代码:func BenchmarkSetBytes(b *testing.B) { b.SetBytes(1024 * 1024) for i : 0; i b.N; i { time.Sleep(1 * time.Second) } }执行结果:6.runN():源码位置:src/testing/benchmark.go// runN runs a single benchmark for the specified number of iterations. func (b *B) runN(n int) { benchmarkLock.Lock() defer benchmarkLock.Unlock() ctx, cancelCtx : context.WithCancel(context.Background()) defer func() { b.runCleanup(normalPanic) b.checkRaces() }() // Try to get a comparable environment for each run // by clearing garbage from previous runs. runtime.GC() b.resetRaces() b.N n b.loopN 0 b.ctx ctx b.cancelCtx cancelCtx b.parallelism 1 b.ResetTimer() b.StartTimer() b.benchFunc(b) b.StopTimer() b.previousN n b.previousDuration b.duration }流程图:7.内存统计:源码位置:src/testing/benchmark.go// BenchmarkResult contains the results of a benchmark run. type BenchmarkResult struct { N int // The number of iterations. T time.Duration // The total time taken. Bytes int64 // Bytes processed in one iteration. MemAllocs uint64 // The total number of memory allocations. MemBytes uint64 // The total number of bytes allocated. // Extra records additional metrics reported by ReportMetric. Extra map[string]float64 }N:最终执行的迭代次数.T:总耗时.Bytes:单词迭代处理的字节数.MemAllocs:总内存分配次数.MemBytes:总内存分配字节数.Extra:自定义性能指标.生成流程(关联runN):AllocsPerOp()函数:// AllocsPerOp returns the allocs/op metric, // which is calculated as r.MemAllocs / r.N. func (r BenchmarkResult) AllocsPerOp() int64 { if v, ok : r.Extra[allocs/op]; ok { return int64(v) } if r.N 0 { return 0 } return int64(r.MemAllocs) / int64(r.N) }流程图:AllocedBytesPerOp()函数:// AllocedBytesPerOp returns the B/op metric, // which is calculated as r.MemBytes / r.N. func (r BenchmarkResult) AllocedBytesPerOp() int64 { if v, ok : r.Extra[B/op]; ok { return int64(v) } if r.N 0 { return 0 } return int64(r.MemBytes) / int64(r.N) }流程图:语雀地址https://www.yuque.com/itbosunmianyi/xg8vfe?《Go.》 密码xbkk 欢迎大家访问.提意见.岁月悠悠.如果大家喜欢我的分享的话.可以关注我的微信公众号念何架构之路