golang 性能測試 (1) 基準性能測試
- 2020 年 4 月 13 日
- 筆記
本文介紹golang 如何做基準性能測試。
編寫完程式碼除了跑必要的單元測試外,還需要考慮程式碼跑起來的性能如何。性能的衡量其實就是程式運行時候進程的記憶體分配,CPU消耗情況。
golang 語言在提供了功能測試的基礎上,提供了豐富的性能測試功能。
SHOW CODE
首先,從一個例子來講起。 隨便寫一個簡單的快速排序,然後和系統自帶的排序做一個性能比較。
如下為簡版快排的程式碼:
package benchmark
import "sort"
func QSort(data []int) {
myqsort(data, 0, len(data)-1)
}
func myqsort(data []int, s, e int) {
if s >= e {
return
}
t := data[s]
i, j := s, e
for i < j {
for ; i < j && data[j] >= t; j-- { }
for ; i < j && data[i] < t; i++ { }
if i < j { break }
data[i], data[j] = data[j], data[i]
i++
j--
}
data[i] = t
myqsort(data, s, i-1)
myqsort(data, i+1, e)
}
然後編寫一個測試的test。
package benchmark
import "testing"
import "math/rand"
import "time"
import "sort"
var ints []int
// 長度為 1w 的數據使用系統自帶排序
func BenchmarkSort10k(t *testing.B) {
slice := ints[0:10000]
t.ResetTimer() // 只考慮下面程式碼的運行事件,所以重置計時器
for i := 0; i < t.N; i++ {
sort.Ints(slice)
}
}
// 長度為 100 的數據使用系統自帶排序
func BenchmarkSort100(t *testing.B) {
slice := ints[0:100]
t.ResetTimer()
for i := 0; i < t.N; i++ {
sort.Ints(slice)
}
}
// 長度為 1w 的數據使用上述程式碼排序
func BenchmarkQsort10k(t *testing.B) {
slice := ints[0:10000]
t.ResetTimer()
for i := 0; i < t.N; i++ {
QSort(slice)
}
}
// 長度為 100 的數據使用上述程式碼排序
func BenchmarkQsort100(t *testing.B) {
slice := ints[0:100]
t.ResetTimer()
for i := 0; i < t.N; i++ {
QSort(slice)
}
}
// 數據初始化,為了保證每次數據都是一致的。
func TestMain(m *testing.M) {
rand.Seed(time.Now().Unix())
ints = make([]int, 10000)
for i := 0; i < 10000; i++ {
ints[i] = rand.Int()
}
m.Run()
}
運行命令 :
# go test -cover -count 3 -benchmem -bench=.
運行結果如下圖:
基準測試,默認將每個方法執行1s中,然後展示執行的次數,每一次執行的耗時, 上述還展示了記憶體每次分配的大小,以及每次benchmark分配的次數。上述的命令行指定了運行次數為3次,顯示程式碼覆蓋率和記憶體分配情況。
從基準測試的結果可以分析出:對於1w數據量的排序,自帶的排序比我的排序演算法要快20倍左右;100數據量的排序,手擼的排序略勝一籌。
從記憶體分析來講,系統自帶的會使用4B的數據,而我的演算法無記憶體分配。
INTRODUCE BENCHMARK
引入golang 提供的 testing
包,寫需要的基準測試的方法(方法名必須以Benchmark開頭, 參數必須為 *testing.B)。
若需要做一些數據初始化的工作,可以如上寫一個TestMain 方法,將數據初始化的工作在這裡完成。
除了這些,可以看*testing.B, *testing.M 的相關方法即可。
最後,只要運行官方提供的 go test -bench=.
命令,即可開始跑基準測試。 當然,還有其他選項可以滿足我們多樣的需求。
例如:
- -cpu 1,2,4 指定運行的cpu 格式
- -count n 指定運行的次數
- -benchtime 每一條測試執行的時間 (默認是1s)
- -bench 指定執行bench的方法,
.
是全部 - -benchmem 顯示記憶體分配情況
其他參數可以通過 go help testflag
查看
WHY SO SLOW
- 我這裡選取的是第一個數作為中位數,數據越大越可能出現傾斜,排序慢的概率也大。
- 正常的排序包中,都會在對小於等於12 個數的數組做排序時使用希爾排序,速度也有很大提升。
除了簡單的做性能測試外,golang 還自帶了性能分析的工具,我們可以快速找出程式碼中的記憶體分配、cpu消耗的核心區,幫助我們解決服務的性能問題。下篇文章將做詳細了解。