跳转到主内容
极星编程网:以代码为星,赴技术山海!

Go语言基准测试benchmark_Golang性能测试编写教程

Go基准测试必须满足命名(Benchmark开头+驼峰)、签名(func BenchmarkXxx(b *testing.B))、文件(_test.go且包名一致)三要素,否则go test -bench=.静默跳过;b.N是框架动态调整的循环次数,用于稳定测量ns/op,不可手动固定。 为什么
go test -bench=.
什么都没输出 大概率是函数没被识别——不是名字不对,就是签名或文件位置错了。Go 的基准测试不报错、不提示,静默跳过是常态。
Benchmark
必须大写开头,后面接驼峰名,比如
BenchmarkMapLookup
;写成
benchmarkMapLookup
或
Benchmark_map_lookup
都无效 签名必须严格是
func BenchmarkXxx(b *testing.B)
:少个
*
(写成
testing.B
)、多一个参数、类型写成
*testing.T
,全都不认 文件必须叫
xxx_test.go
,且包声明和被测代码一致(不能是
package main
单独测) 如果函数里有
log.Fatal
、
panic
或未处理的
error
导致提前退出,
b.N
可能为 0,输出里会显示
benchmarked 0 times
b.N
是什么,为什么不能手动写
for i := 0; i < 1000000
b.N
是框架动态决定的迭代次数,目标是让整个循环体总耗时稳定在约 1 秒(可由
-benchtime
调整)。它不是固定值,同一函数在不同机器、不同负载下,
b.N
可能差几倍。 手写固定次数会让
ns/op
失去可比性:CPU 忙时跑得慢,你硬设 100 万次,结果可能跑 5 秒;空闲时又只跑 200ms,抖动极大
go test -benchtime=3s
这类参数只对
b.N
有效;手动循环完全无视这些控制 真正要测单次开销,就得靠
b.N
—— 它让框架自己找“足够多但不过载”的量级,最终算出的
ns/op
才是纳秒级稳定值 极慢操作(如含
time.Sleep
或 I/O)除外,此时应加
b.ReportAllocs()
和
-benchmem
看分配,而不是调
b.N
怎么把初始化代码从计时里剥离开 setup 代码(比如
make(map[int]int)
、读配置、建临时文件)如果混在主循环里,会被计入
ns/op
,结果就不是“逻辑本身”,而是“初始化 + 逻辑 × N”。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 正确顺序:先做 setup → 调
b.StopTimer()
或直接
b.ResetTimer()
(后者隐含先停再启)→ 再进
for i := 0; i < b.N
循环 别在循环里重复做 setup:比如每次迭代都
json.Marshal
同一数据,测的是序列化+主逻辑,不是主逻辑 副作用需重置:如果函数修改全局变量或缓存,每次迭代前要在
b.StopTimer()
区块内恢复初始状态 嵌套子 benchmark(
b.Run
)时,父函数的
ResetTimer
对子函数无效,每个子 benchmark 必须自己管理计时 为什么测出来总是
0 ns/op
或
0 B/op
不是函数快,是编译器优化掉了——它发现你的计算没产生可观测效果,整段逻辑被删了。 立即学习 “ go语言免费学习笔记(深入) ”; 最常见原因:没用返回值,也没让它影响任何变量。例如
compute(); _ = result
不够,
_ = result
还可能被二次优化 防优化手段:把结果赋给包级变量(
var blackhole int
),或在循环末尾加
blackhole = blackhole
;更稳妥的是用
b.ReportMetric
0 B/op
不代表没分配:可能是逃逸分析成功,分配压栈了;加
-gcflags="-m"
看关键变量是否逃逸,比看
B/op
更准
b.ReportAllocs()
必须放在
for
循环之前才生效;放错位置会导致
allocs/op
恒为 0,误判“零分配” 字符串拼接、
append
切片、闭包捕获都可能隐式堆分配,
-benchmem
不加就看不到,但瓶颈常在这儿 真实场景里最难的不是让 Benchmark 跑起来,而是确认它测的真是你要优化的那一小段逻辑——哪怕只是变量作用域挪了一行,或者
ResetTimer
少调一次,结果就可能偏出两个数量级。

相关文章