golang性能测试及优化(上)

以斐波那契数列作为测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package fib

func Fib(n int) int {
switch n {
case 0:
return 0
case 1:
return 1
case 2:
return 2
default:
return Fib(n-1) + Fib(n-2)
}
}

性能测试Benchmarks的用法和单元测试类似,也是用的testing,性能测试用*testing.B代替*testing.T

单元测试日志
方法 说明
Log 打印日志,同时结束测试
Logf 格式化打印日志,同时结束测试
Error 打印错误日志,同时结束测试
Errorf 格式化打印错误日志,同时结束测试
Fatal 打印致命日志,同时结束测试
Fatalf 格式化打印致命日志,同时结束测试

以上方法testing.B也可以使用。

编写性能测试fib_test.go:

1
2
3
4
5
6
7
8
9
10
11
package fib

import (
"testing"
)

func BenchmarkFib20(b *testing.B) {
for n := 0; n < b.N; n++ {
Fib(20) // run the Fib function b.N times
}
}

运行go test -bench=., 结果:

goos: linux
goarch: amd64
BenchmarkFib20-8 50000 37932 ns/op
PASS

Windows 下使用 go test 命令行时,-bench=.应写为-bench="."

参数-cpu表示开启CPU的核数,通过GOMAXPROCS进行控制,比如-cpu=1,2,4表示分别开启1核、2核、4核进行测试:

$ go test -bench=. -cpu=1,2,4
goos: linux
goarch: amd64
BenchmarkFib20 50000 36877 ns/op
BenchmarkFib20-2 50000 36843 ns/op
BenchmarkFib20-4 30000 36231 ns/op

参数-benchtime可以让我们自己控制测试的时间,比如:

$ go test -bench=. -benchtime=3s
goos: linux
goarch: amd64
BenchmarkFib20-8 100000 46070 ns/op
PASS
ok _/home/shikanon/study/fib 5.018s

你会发现总的运行时间并不是3s,而且不同的运行其时间会有差异,这主要是因为由于GC活动、后台运行程序、内存位置、CPU的调整频率所影响。

为了获得稳定的统计,我们可以用-count参数来获得多次测试。

$ go test -bench=. -count=10
goos: linux
goarch: amd64
BenchmarkFib20-8 50000 38395 ns/op
BenchmarkFib20-8 50000 37019 ns/op
BenchmarkFib20-8 50000 36974 ns/op
BenchmarkFib20-8 50000 41050 ns/op
BenchmarkFib20-8 50000 36131 ns/op
BenchmarkFib20-8 30000 37317 ns/op
BenchmarkFib20-8 30000 42872 ns/op
BenchmarkFib20-8 30000 41711 ns/op
BenchmarkFib20-8 50000 36517 ns/op
BenchmarkFib20-8 50000 40240 ns/op
PASS
ok _/home/shikanon/study/fib 20.996s

接下来可以利用benchstat包计算平均值,benchstat是官方pref项目中的命令行工具,可以用来做各种性能测试的分析,比如计算多次测试的平均值核方差:

$benchstat old.txt
name time/op
Fib20-8 39.4µs ±13%

ps:由于prefgolang/x中的包,我们需要git clone下载下来,然后到benchstat目录下做编译go build -o $GOROOT/bin/benchstat main.go

也可以用来计算两种不同方法进行比较,看他们的p值是否显著。在对比两个或以上的用例时可以用go test -c生成二进制测试文件。

./fib2.test -bench=. -test.count=10 > old.txt
./fib.test -bench=. -test.count=10 > new.txt
$ benchstat old.txt new.txt
name old time/op new time/op delta
Fib20-8 44.3µs ± 6% 25.6µs ± 2% -42.31% (p=0.000 n=10+10)

参考

https://dave.cheney.net/high-performance-go-workshop/dotgo-paris.html

shikanon wechat
欢迎您扫一扫,订阅我滴↑↑↑的微信公众号!