46.1 效能基準測試在Go語言中是“一等公民”
效能基準測試在Go語言中和普通的單元測試一樣被原生支援的,得到的是“一等公民”的待遇。
我們可以像對普通單元測試那樣在*_test.go檔案中建立被測物件的效能基準測試,每個以Benchmark字首開頭的函式都會被當作一個獨立的效能基準測試。
46.2 順序執行和並行執行的效能基準測試
#透過-benchtime手動指定b.N的值
go test -v -benchtime 5x -bench . sequential_test.go
#透過-count手動指定執行次數
go test -v -count 2 -bench . sequential_test.go
#透過-cpu手動指定GOMAXPROCS
go test -v -bench . paralell_test.go -cpu 2,4,8
go test -v -bench . paralell_test.go -cpu=2
1.順序執行
var (
m map[int64]struct{} = make(map[int64]struct{}, 10)
mu sync.Mutex
round int64 = 1
)
func BenchmarkSequential(b *testing.B) {
fmt.Printf("\ngoroutine[%d] enter BenchmarkSequential: round[%d], b.N[%d]\n",
tls.ID(), atomic.LoadInt64(&round), b.N)
defer func() {
atomic.AddInt64(&round, 1)
}()
for i := 0; i < b.N; i++ {
mu.Lock()
_, ok := m[round]
if !ok {
m[round] = struct{}{}
fmt.Printf("goroutine[%d] enter loop in BenchmarkSequential: round[%d], b.N[%d]\n",
tls.ID(), atomic.LoadInt64(&round), b.N)
}
mu.Unlock()
}
fmt.Printf("goroutine[%d] exit BenchmarkSequential: round[%d], b.N[%d]\n",
tls.ID(), atomic.LoadInt64(&round), b.N)
}
2.並行執行
var (
m map[int64]int = make(map[int64]int, 20)
mu sync.Mutex
round int64 = 1
)
func BenchmarkParalell(b *testing.B) {
fmt.Printf("\ngoroutine[%d] enter BenchmarkParalell: round[%d], b.N[%d]\n",
tls.ID(), atomic.LoadInt64(&round), b.N)
defer func() {
atomic.AddInt64(&round, 1)
}()
b.RunParallel(func(pb *testing.PB) {
id := tls.ID()
fmt.Printf("goroutine[%d] enter loop func in BenchmarkParalell: round[%d], b.N[%d]\n", tls.ID(), atomic.LoadInt64(&round), b.N)
for pb.Next() {
mu.Lock()
_, ok := m[id]
if !ok {
m[id] = 1
} else {
m[id] = m[id] + 1
}
mu.Unlock()
}
mu.Lock()
count := m[id]
mu.Unlock()
fmt.Printf("goroutine[%d] exit loop func in BenchmarkParalell: round[%d], loop[%d]\n", tls.ID(), atomic.LoadInt64(&round), count)
})
fmt.Printf("goroutine[%d] exit BenchmarkParalell: round[%d], b.N[%d]\n",
tls.ID(), atomic.LoadInt64(&round), b.N)
}
46.3 使用效能基準比較工具
benchcmp已廢棄,官方推薦用經過統計學方法處理的benchstat。
46.4 排除額外干擾,讓基準測試更精確
使用testing.B提供的定時器操作方法排除額外干擾,讓基準測試更精確,但不要在RunParallel中使用ResetTimer、StartTimer、StopTimer,因為它們具有全域性副作用。