Go 的 testing 包基准测试自动记录 CPU 时间和内存分配;CPU 时间以 ns/op 表示单次执行平均纳秒数,反映执行快慢,通过 go test -bench 运行。

Go 的 testing 包自带的 benchmark 功能可以自动记录 CPU 时间和内存分配情况,无需额外工具。关键在于写规范的基准测试函数,并用 go test -bench 正确运行。
CPU 时间:看 BenchmarkXXX 输出的 ns/op
每次 benchmark 运行时,Go 会多次执行被测函数(默认至少 1 秒),最终报告单次执行的平均纳秒数(ns/op)。这个值直接反映 CPU 消耗快慢。
示例:
func BenchmarkAdd(b *testing.B) {for i := 0; i _ = add(1, 2)
}
}
运行:go test -bench=BenchmarkAdd -benchmem
立即学习“go语言免费学习笔记(深入)”;
输出中类似 BenchmarkAdd-8 1000000000 0.32 ns/op 表示单次调用平均耗时 0.32 纳秒。
-
注意循环体必须用
b.N控制次数,不能写死数字(如1000000),否则结果不准确 - 避免在循环内做无关操作(如打印、文件读写),否则干扰 CPU 时间测量
- 若函数本身极快(如纯计算),可考虑用
-benchtime=10s延长采样时间提升精度
内存分配:关注 Benchmem 输出的 B/op 和 allocs/op
启用 -benchmem 后,输出会追加两列:B/op(每次运行分配的字节数)和 allocs/op(每次运行发生的堆内存分配次数)。这两项反映内存压力大小。
例如:BenchmarkMapCreate-8 5000000 242 ns/op 128 B/op 2 allocs/op
-
B/op高通常意味着对象体积大或复制多(如返回大结构体副本、频繁拼接字符串) -
allocs/op高往往说明有隐式堆分配(如切片扩容、闭包捕获变量、interface{} 装箱) - 想定位具体哪行触发分配?可用
go tool pprof结合-memprofile生成内存分析文件
对比不同实现:用 -benchmem -benchtime=3s 确保可比性
横向比较多个 benchmark 时,需统一运行时长和环境,避免因默认采样差异导致误判。
- 固定
-benchtime(如3s)让每组测试跑足够久,减少随机波动 - 加上
-count=5可跑 5 轮取平均值,用benchstat工具分析显著性差异 - 禁用 GC 干扰?一般不用手动干预;Go benchmark 本身已忽略 GC 时间,但若测试含大量短生命周期对象,可加
GOGC=off临时关闭 GC 观察真实分配行为(仅调试用)
进阶技巧:用 b.ReportAllocs() 和 b.StopTimer() 精细控制
某些场景下,初始化或清理逻辑不应计入指标,这时需要手动控制计时与统计范围。
-
b.ReportAllocs()显式开启内存统计(部分旧版本需手动调用) -
b.StopTimer()暂停计时和内存统计,适合放预热、建缓存、开连接等准备代码 -
b.StartTimer()恢复统计,确保只测核心逻辑 - 示例:测试 map 查找前先构造百万级 map,这部分应
StopTimer,只对lookup()计时











