Go基准测试函数名必须以Benchmark开头,定义在_test.go文件中,仅接收*testing.B参数且无返回值,主体需用b.N循环并调用b.ResetTimer()。

Go基准测试函数名必须以Benchmark开头
Go的testing包只识别形如BenchmarkXXX的函数为基准测试,且必须接收*testing.B参数。名字不满足规则(比如写成TestBenchmark或benchFoo)会导致go test -bench完全忽略该函数。
常见错误:把基准测试和普通单元测试混写在同一文件但没注意命名规范,结果-bench=.跑出来是no benchmarks to run。
- 函数必须定义在
_test.go文件中 - 首字母大写的
XXX部分建议体现被测逻辑,例如BenchmarkMapInsert、BenchmarkJSONMarshal - 不能有返回值,也不能额外参数(仅
*testing.B)
基准测试主体必须调用b.N循环
*testing.B的b.N不是固定次数,而是由Go测试框架根据预热和稳定性自动确定的迭代次数。你必须在b.ResetTimer()之后、实际测量代码里显式使用for i := 0; i 包裹待测逻辑,否则测的是0次或1次,结果无意义。
容易踩的坑:直接在循环外执行一次操作,或者用b.ReportAllocs()但忘了加循环——这时b.N可能是1,所有耗时/内存数据都失真。
立即学习“go语言免费学习笔记(深入)”;
- 不要手动设
b.N = 10000,它会被框架覆盖 - 耗时敏感的操作(如初始化开销大的对象)应放在
b.ResetTimer()之前 - 如果要排除某段预处理时间,用
b.StopTimer()和b.StartTimer()控制计时区间
运行基准测试必须加-bench参数
go test默认不运行任何Benchmark函数,必须显式传参。最常用的是go test -bench=.(点号表示匹配所有),也可以用正则精确指定,比如go test -bench=BenchmarkJSON。
注意:-bench会自动启用-cpuprofile等底层支持,但不会运行Test函数——除非同时加-run。这点常被忽略,导致误以为“基准测试失败”其实是没跑起来。
- 加
-benchmem可同时显示内存分配统计(推荐必加) - 加
-benchtime=5s可延长总运行时间,让结果更稳定(默认1秒) - 加
-count=3可重复运行三次取平均值,避免单次抖动干扰
func BenchmarkAdd(b *testing.B) {
var x, y = 1, 2
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = x + y
}
}
这个例子看起来简单,但漏掉b.ResetTimer()或没用b.N循环,就不是有效的基准测试。真实场景中,初始化DB连接、构建大结构体、预热缓存这些动作,都需要仔细安排在计时开关之间。










