go 的測試工具 go test
有 benchmark 工具可以使用。
不用自己寫工具就可以很輕鬆的測試程式碼效能。
開始寫 benchmark 測試#
- 建立
_test.go
結尾的檔案 - function 要以
Benchmark
開頭 - 使用
b *testing.B
參數 - 將要測試的程式放到
b.N
的 for 迴圈內
範例如下:
1
2
3
4
5
6
7
8
| // main.go
func Sum(s []int) int {
sum := 0
for i := 0; i < len(s); i++ {
sum += s[i]
}
return sum
}
|
1
2
3
4
5
6
| // main_test.go
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
Sum([]int{1, 2, 3})
}
}
|
執行 benckmark#
- 執行
go test
指令加上 -bench
參數 -bench
一樣支援使用正規表達式,執行符合的測試
輸出結果:
1
2
| BenchmarkSum-8 610364305 1.978 ns/op
PASS
|
輸出結果說明
-8
代表 GOMAXPROCS
的值,也就是使用的核心數- 迴圈執行 610364305 次
- 執行速度為每次 1.978 ns
一些 benchmark 相關指令參數#
-benchtime t
- 指定 benchmark 測試迴圈跑滿多少時間 ex. -benchtime 10s, 跑 10 秒
- 預設值為 1 秒
- 可以用 x 指定執行次數 ex. -benchtime 100x, 跑 100 次
-count n
- 指定 benchmark 要跑幾輪測試
- 預設 1 次
-cpu 1,2,4
-benchmem
測試 json decode 到 Map 跟 struct#
我們準備另一個 benchmark 測試
1
2
3
4
5
| // main.go
type Book struct {
Title string `json:"title"`
Author string `json:"author"`
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // main_test.go
func BenchmarkDecode2Struct(b *testing.B) {
jsonString := []byte("{\"title\":\"Document\",\"author\":\"me\"}")
for i := 0; i < b.N; i++ {
b := Book{}
json.Unmarshal(jsonString, &b)
}
}
func BenchmarkDecode2Map(b *testing.B) {
jsonString := []byte("{\"title\":\"Document\",\"author\":\"me\"}")
for i := 0; i < b.N; i++ {
m := make(map[string]string)
json.Unmarshal(jsonString, &m)
}
}
|
這次測試我們增加一些內容,先是多測幾次比較誤差,並統計記憶體使用情況,指令跟結果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| go test -bench=. -count=5 -benchmem
goos: darwin
goarch: amd64
pkg: github.com/nyogjtrc/practice-go/example-benchmark
cpu: Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
BenchmarkSum-8 448784319 2.662 ns/op 0 B/op 0 allocs/op
BenchmarkSum-8 446790114 2.732 ns/op 0 B/op 0 allocs/op
BenchmarkSum-8 441891258 2.702 ns/op 0 B/op 0 allocs/op
BenchmarkSum-8 449093973 2.669 ns/op 0 B/op 0 allocs/op
BenchmarkSum-8 445117809 2.673 ns/op 0 B/op 0 allocs/op
BenchmarkDecode2Struct-8 1542450 778.2 ns/op 264 B/op 7 allocs/op
BenchmarkDecode2Struct-8 1548220 783.6 ns/op 264 B/op 7 allocs/op
BenchmarkDecode2Struct-8 1534435 787.3 ns/op 264 B/op 7 allocs/op
BenchmarkDecode2Struct-8 1538522 790.6 ns/op 264 B/op 7 allocs/op
BenchmarkDecode2Struct-8 1545883 795.0 ns/op 264 B/op 7 allocs/op
BenchmarkDecode2Map-8 874519 1190 ns/op 616 B/op 14 allocs/op
BenchmarkDecode2Map-8 913914 1206 ns/op 616 B/op 14 allocs/op
BenchmarkDecode2Map-8 1010119 1204 ns/op 616 B/op 14 allocs/op
BenchmarkDecode2Map-8 893706 1208 ns/op 616 B/op 14 allocs/op
BenchmarkDecode2Map-8 954352 1195 ns/op 616 B/op 14 allocs/op
PASS
ok github.com/nyogjtrc/practice-go/example-benchmark 24.121s
|
輸出結果說明
B/op
: 每次迴圈的記憶體用量allocs/op
: 每次迴圈的記憶體分配次數
Reference#