Golang test模块benchmark性能测试(转载)

1. 概述

基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器。

在日常生活中,我们使用速度 m/s(单位时间内物体移动的距离)大小来衡量一辆跑车的性能,同理,我们可以使用”单位时间内程序运行的次数“来衡量程序的性能。

注意:在进行基准测试时,硬件资源直接影响测试结果,为了保证测试结果的可重复性,需要尽可能地保证硬件资源一致。(单一变量原则)

2. benchmark示例

  1. 创建文件 main.go,编写我们的被测函数

  2. 创建文件 main_test.go ,编写基准测试用例

    • 位于同一个 package 内的测试文件以 _test.go 结尾,其中的测试用例格式为 func BenchmarkXxx(b *testing.B) ,注意 Xxx 首字母要大写(即驼峰命名法)
    • 函数内被测函数循环执行 b.N 次

  3. 开始运行

3. benchmark执行参数

  1. go test [packages] 指定测试范围

    方法一 方法二
    运行当前 package 内的用例 go test packageName go test .
    运行子 package 内的用例 go test packageName/subName go test ./subName
    递归运行所有的用例 go test packageName/… go test ./…
  2. benmark执行

    命令默认不执行 benchmark 测试,需要加上 -bench 参数,该参数支持正则表达式,只有匹配到的测试用例才会执行,使用 . 则运行所有测试用例

  3. BenchmarkFib10-4 中的 4 即 GOMAXPROCS,默认等于 CPU 核数

  4. 执行参数解释

    • 3287449 357 ns/op 表示单位时间内(默认是1s)被测函数运行了 3287449 次,每次运行耗时 357ns,
    • 3287449*357ns=1.173s(耗时比 1s 略多,因为测试用例执行、销毁等是需要时间的)
    • ok learnGolang 3.418s 表示本次测试总耗时

4. benchmark进阶参数

4.1. -benchtime t

在高中物理学中,由于测试物体瞬时速度不好实现,我们可以让物体多移动一段时间,然后采用“总距离/时间段”算出平均速度来代替瞬时速度。

go benchmark 默认测试时间是 1s,同样的原理,为了提升测试准确度,我们可以使用该参数适当增加时长。

还是高中物理学,我们也可以指定物理移动的距离,然后测量所耗费的时间,计算平均速度。

该参数还支持特殊的形式 Nx ,用来指定被测程序的运行次数。

4.2. -count n

同样类似与测量物体速度,为了提升精确度,我们多做几次测试。

4.3. -cpu n

该参数可以设置 benchmark 所使用的 CPU 核数。

下面我们模拟一次多核并行计算的例子,并观察设置不同核数后的测试结果

从运行结果看出,随着 CPU 核数的增加,性能逐步提升,但是到一定阈值后,性能趋于稳定,此时再增加 CPU 核数,性能反而下降,因为 CPU 核心之间的切换也是需要成本的。

4.4. -benchmem

除了速度,内存分配情况也是需要我们重点关注的指标。

go 语言中,slice 有一个 cap 属性,合理的设置该值,可以减少内存分配次数,分配大小,提升程序性能。

可以看到前者每次执行会分配 386297 字节的内存,约等于后者的 3.76 倍,每次执行会分配内存 20 次,是后者的 20 倍。

4.5. ResetTimer

If a benchmark needs some expensive setup before running, the timer may be reset

如果在整个 benchmark 执行前,需要一些耗时的准备工作,我们需要将这部分耗时忽略掉

4.6. StopTimer & StartTimer

StopTimer stops timing a test. This can be used to pause the timer while performing complex initialization that you don’t want to measure.

StartTimer starts timing a test. This function is called automatically before a benchmark starts, but it can also be used to resume timing after a call to StopTimer.

如果在被测函数每次执行前,需要一些准备工作,我们可以使用 StopTimer 暂停计时,准备工作完成后,使用 StartTimer 继续计时。

4.7. 执行时性能

  • 添加-memprofile 和 -cpuprofile参数,benchmark执行后会生成两个文件,用于cpu和内存相关分析的问题

  • 这里可以go tool自带pprof进行性能分析;执行这两个命令后,会生成性能分析图

  • 保证环境安装了,graphviz可视化软件,以下命令安装graphviz

    性能分析结果:

赞赏

微信赞赏支付宝赞赏

发表评论

邮箱地址不会被公开。 必填项已用*标注