go test - 基准测试
ddatsh
稳定的测试环境
性能测试受环境影响很大,为保证测试的可重复性,尽可能地保持测试环境的稳定
- 机器处于闲置状态,测试时不要执行其他任务,也不要和其他人共享硬件资源
- 机器是否关闭了节能模式,一般笔记本会默认打开这个模式,测试时关闭
- 避免使用虚拟机和云主机进行测试,虚拟机和云主机 CPU 和内存一般会超分配,性能表现会非常地不稳定
规则
- 测试函数需要位于
*_test
文件中 - 函数名称必须以
Benchmark
开头 - 函数必须接受
*testing.B
作为唯一形参 - 测试函数必须包含一个
for
循环(b.N
为其上限,b.N, go 会根据系统情况生成)
// fib.go
package main
func Fib(n int) int {
if n == 0 || n == 1 {
return n
}
return Fib(n-2) + Fib(n-1)
}
// fib_test.go
package main
import "testing"
func BenchmarkFib(b *testing.B) {
for n := 0; n < b.N; n++ {
Fib(30) // run fib(30) b.N times
}
}
默认 go test 会运行单元测试,可以使用-run=匹配一个从来没有的单元测试方法,过滤掉单元测试的输出(如 -run=^$)
go test -run=XXX -bench=. -benchmem -cpuprofile cpu.out -memprofile mem.out
benchmark 默认至少运行1秒。 -benchtime=Ns
指定具体运行时间
-count=N
表示运行该基准测试多少次。注意:不是多少次op或迭代
函数名后的数字表示 GOMAXPROCS
的值,默认是 CPU 的核数。该值可以在执行测试时设置,例如 GOMAXPROCS=2 go test ...
benchstat
go install golang.org/x/perf/cmd/benchstat@latest
package main
import "testing"
//go:noinline
func max(a, b int) int {
if a > b {
return a
}
return b
}
var Result int
func BenchmarkMax(b *testing.B) {
var r int
for i := 0; i < b.N; i++ {
r = max(-1, i)
}
Result = r
}
go test -bench=. -count=10 -gcflags="-l -N" > base.txt
go test -bench=. -count=10 > noinline.txt
go test -bench=. -count=10 > inline.txt
benchstat base.txt noinline.txt inline.txt
goos: windows
goarch: amd64
pkg: test
cpu: 13th Gen Intel(R) Core(TM) i5-13600KF
│ base.txt │ noinline.txt │ inline.txt │
│ sec/op │ sec/op vs base │ sec/op vs base │
Max-20 0.9940n ± 1% 0.4947n ± 1% -50.23% (p=0.000 n=10) 0.1358n ± 1% -86.33% (p=0.000 n=10)
如果 delta 一列,值是~
,没有显示百分比,说明两次测试结果没有显著差异
go test -cover