b.N 是 Go 基准测试框架自动设定的迭代基数,表示当前 BenchmarkXxx 函数中被测逻辑必须执行 b.N 次,而非手动写死的循环次数。
什么是 b.N?它不是你写的循环次数
b.N 是 Go 基准测试框架自动设定的迭代基数,表示当前这轮 BenchmarkXxx 函数里,被测逻辑**必须执行 b.N 次**——但它绝不是你手动写死的 for i := 0; i 中那个 1000。
它的值由 go test 运行时动态决定:框架会反复试探,调整 b.N,直到整个基准函数(含你的循环体)总耗时接近 -benchtime(默认 1 秒)。所以:
- 一个空函数可能跑出
b.N = 12345678; - 一个带
time.Sleep(10 * time.Millisecond)的函数,b.N可能只有 90 左右; - 同一段代码,在不同机器、不同 GC 压力下,
b.N值天然不同——所以只比本机相对值,跨机对比ns/op才有意义。
为什么不能在循环里做初始化?b.ResetTimer() 怎么用
基准测试只计时「纯被测逻辑」,任何 setup/teardown 都不该污染计时。常见错误是这样写:
func BenchmarkBad(b *testing.B) {
for i := 0; i < b.N; i++ {
if i == 0 {
expensiveSetup() // ❌ 错!计时已开始,setup 被计入
}
targetFunc()
}
}
正确做法是把初始化提到循环外,并用 b.ResetTimer() 重置计时起点: