What is
Benchmark是Go testing测试框架提供的基准测试功能,能对一段代码进行性能测试。
下面是一段性能测试的结果:
Go Benchmark提供的参数包括(按照结果的先后顺序):
- 重复测试次数:该指标越高,结果越可靠
- 单次重复的平均耗时:xxx纳秒每次操作,越低越好
- Heap Memory:每次的内存分配,越低越好
- 单次测试的内存分配次数:越低越好
使用Benchmark可以做许多测试,比如测试时间复杂度,就可以根据Benchmark的指标随着次数的增长的比例来判断。
How to use
1 Before Use
首先要注意的是,要尽量保证测试环境的稳定。否则,你重复测试的结果是没有可比性的。通常可以通过一下方式使得环境趋于稳定:
- 当前机器处于闲置状态,不执行其他任务,也不要共享硬件资源
- 避免使用虚机和进行测试。通常,为了提高资源利用率,虚拟机和云主机CPU和内存会超分配,导致性能不稳定
关于云主机超分:通常是超售CPU能力,比如,当你的CPU长时间闲置时,也许你的性能会被二次销售给别人。可以通过Linux上Steal Time的指标来衡量自己被偷走的CPU占用时间
2 Case
我们就简单地,测试一下Go语言字符串的拼接方式。
在
_test.go
文件中,写Benchmark测试函数func BenchmarkPlus(b *testing.B) {
var str string
for n := 0;n < b.N; n++ {
str += "helloMyWorld"
}
}
- Benchmark也在_test.go文件中,使用的是TB中的B
- 函数名以Benchmark开头,B.N表示的是用例测试的次数,这个是自动定的
使用
go test -bench <module name>/<package name>
运行性能测试用例,模块名和包名可选。且-bench
参数支持正则表达式,仅执行匹配的测试,如-bench='Fib$'
$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: try
cpu: VirtualApple @ 2.50GHz
BenchmarkPlus-8 148148 82902 ns/op 892933 B/op 1 allocs/op
PASS
ok try 12.453s
BenchmarkPlus-8
中的-8
,是GOMAXPROCS
,默认等于CPU核数,可以使用-cpu=2,4
的形式进行修改。CPU的核数主要影响设计并行的函数-benchmem
用于查看内存分配的信息-benchtime=10s
设置测试时间(实际执行时间因为还有编译、执行、销毁等阶段,会大于这个时间),-benctime=10x
可以设置次数,-count
可以设置Benchmark的轮数
3 Details
通常,我们只想关注我们核心代码的性能情况,而性能测试所统计的时间会包括编译、用例的准备销毁等开销,所以可以使用内置的方法来忽略掉这些开销。当然,由于循环的部分是我们自己实现的,所以这部分的开销通常是不会很大的,所以我觉得,可能意义不那么明显。
B.ResetTimer()
重置计时器,字面意思,很好理解。在你的测试代码前使用,就可以忽略掉准备的时间
B.StopTimer & StartTimer()
B.SetBytes()
该函数用于设置字节数,感觉使用频率会非常的低,可以去《Go专家编程》中看看更详细的用例
Deeper
1 B.N
首先是基准测试的循环次数B.N
,这个并不是由我们手动设置的,而是由内置的函数进行测算的。相关的伪代码仍然可以在专家编程中看到,这里就简述一下思想: