Go性能对比需用go test -bench编写Benchmark函数,命名以BenchmarkXxx开头,用b.ResetTimer()排除初始化耗时,b.ReportAllocs()和b.SetBytes()统计内存,配合benchstat多轮采样分析ns/op、B/op、allocs/op指标。

在 Go 中对比不同实现的性能,核心是使用 go test -bench 配合标准 testing.B 类型编写基准测试(benchmark),并通过 benchstat 工具进行统计分析。关键不是“跑一次看耗时”,而是让测试可复现、可对比、能排除噪声。
写规范的 Benchmark 函数
每个 benchmark 函数必须以 BenchmarkXxx 命名,接收 *testing.B 参数,并在 b.N 次循环中执行待测逻辑。注意:初始化操作(如构造数据)应放在 b.ResetTimer() 之前,避免计入耗时。
- 用
b.ReportAllocs()开启内存分配统计 - 用
b.SetBytes(n)告知每次操作处理的数据量(便于计算吞吐,如 B/op、MB/s) - 避免在循环内做非目标逻辑(如 fmt.Print、time.Now)
- 示例片段:
data := make(map[int]int, 1000)
for i := 0; i b.ResetTimer()
for i := 0; i sum := 0
for _, v := range data { sum += v }
}
}
一次运行多个实现并命名区分
把不同算法/结构的 benchmark 放在同一文件(如 compare_bench_test.go),函数名体现差异,例如:
-
BenchmarkSliceFilterStd(用 for 循环手动过滤) -
BenchmarkSliceFilterCopy(预分配+copy) -
BenchmarkSliceFilterAppend(append 动态扩容)
这样运行 go test -bench=. 就能一次性输出所有结果,横向对比更直观。
立即学习“go语言免费学习笔记(深入)”;
用 benchstat 做统计对比
单次 benchmark 结果受 GC、CPU 调度等干扰,直接比数字不可靠。推荐用官方工具 benchstat 计算均值、置信区间和显著性差异:
- 安装:
benchstat - 采集多组数据:
go install golang.org/x/perf/cmd/benchstat@latest(旧实现)
go test -bench=Filter -count=5 > old.txt(新实现) - 对比:
go test -bench=Filter -count=5 > new.txt→ 输出带 p 值和提升比例的表格
它会自动忽略离群值,告诉你“新实现快 1.8×,p
关注关键指标,不止看 ns/op
一个 benchmark 的输出通常包含三列:benchstat old.txt new.txt、ns/op、B/op。它们分别代表:
- ns/op:单次操作平均纳秒数 → 衡量 CPU 时间效率
- B/op:每次操作分配的字节数 → 影响 GC 压力和内存带宽
- allocs/op:每次操作的堆分配次数 → 每次 alloc 都有开销,尤其小对象高频分配很伤
比如两个实现 ns/op 相近,但一个 allocs/op 是 0,另一个是 5 —— 后者长期运行可能因 GC 拖慢整体吞吐,不能只看第一列。
基本上就这些。不复杂但容易忽略细节:重置计时器、多次采样、看内存而非仅看时间。真正对比性能,比的是稳定、可复现、有统计意义的差异。











