Lekcje modułu (3/5)
Benchmarki i profile
Oprócz testów funkcjonalnych, go test ma również wbudowane testy porównawcze (BenchmarkXxx) i obsługuje profile procesora i pamięci (pprof). Wszystko bez zewnętrznych zależności.
Kształt benchmarku
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Sum(2, 3)
}
}Charakterystyka:
- Dokładny podpis:
func BenchmarkXxx(b *testing.B). - Pętla musi wykonywać iteracje
b.N: struktura automatycznie dostosowujeb.N, zaczynając od 1 i rosnąc, aż pomiar się ustabilizuje (domyślnie ~ 1 sekunda). - Wynikiem jest
ns/op(nanosekundy na operację), a w przypadku-benchmemtakżeB/opiallocs/op.
Typowe polecenia
go test -bench=. ./... # all benchmarks
go test -bench=Sum -benchmem # only Sum, with memory info
go test -bench=. -benchtime=5s # each benchmark for 5 seconds
go test -bench=. -cpuprofile=cpu.out # generate a CPU profileTypowe wyjście:
BenchmarkSum-8 1000000000 0.31 ns/op
-8 jest wartością GOMAXPROCS. 0.31 ns/op to średni czas połączenia.
Kosztowna konfiguracja: b.ResetTimer
Jeśli przed pętlą masz długi etap przygotowawczy, wyklucz ją z pomiaru:
func BenchmarkSearch(b *testing.B) {
data := buildLargeSlice(1_000_000) // expensive
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = Search(data, 42)
}
}Przydatne warianty:
b.StopTimer()/b.StartTimer()— pauza pomiaru wokół nieciekawej fazy (przydatne w pętli).b.ReportAllocs()— raportowanie alokacji siły nawet bez-benchmem.
Tabela porównawcza z b.Run
Podobnie jak t.Run do testów, istnieje b.Run do testów parametrycznych:
func BenchmarkSplit(b *testing.B) {
for _, size := range []int{10, 1000, 100000} {
b.Run(fmt.Sprintf("n=%d", size), func(b *testing.B) {
s := strings.Repeat("a,", size)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = strings.Split(s, ",")
}
})
}
}Wiersze wyjściowe, takie jak BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... idealne do wykresów skalujących.
Porównanie dwóch implementacji z benchstat
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txtbenchstat (w golang.org/x/perf/cmd/benchstat) oblicza średnią, odchylenie standardowe i istotność statystyczną różnicy.
Ćwiczenia
Zdefiniuj BenchmarkSum za pomocą pętli nad b.N, która wywołuje Sum(2, 3).
Rozwiązanie dostępne po 3 próbach
Dodaj b.ResetTimer PO drogiej konfiguracji, przed pętlą, aby konfiguracja nie została uwzględniona w pomiarze.
Rozwiązanie dostępne po 3 próbach
Która flaga obsługuje wszystkie testy porównawcze w pakiecie?
$ go test ???