Lecții din modul (3/5)
Benchmark-uri și profile
Pe lângă testele funcționale, go test are și benchmarks (BenchmarkXxx) și acceptă profilele CPU și memorie (pprof). Toate fără dependențe externe.
Forma unui reper
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Sum(2, 3)
}
}Caracteristici:
- Semnătură exactă:
func BenchmarkXxx(b *testing.B). - Bucla trebuie să ruleze
b.Niterații: cadrul ajusteazăb.Nautomat, începând de la 1 și crescând până când măsurarea se stabilizează (~1 secundă în mod implicit). - Rezultatul este
ns/op(nanosecunde per operație) și, cu-benchmem, de asemeneaB/opșiallocs/op.
Comenzi tipice
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 profileIeșire tipică:
BenchmarkSum-8 1000000000 0.31 ns/op
-8 este valoarea GOMAXPROCS. 0.31 ns/op este durata medie per apel.
Configurare costisitoare: b.ResetTimer
Dacă aveți un pas lung de pregătire înainte de buclă, excludeți-l din măsurare:
func BenchmarkSearch(b *testing.B) {
data := buildLargeSlice(1_000_000) // expensive
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = Search(data, 42)
}
}Variante utile:
b.StopTimer()/b.StartTimer()— întrerupeți măsurarea în jurul unei faze neinteresante (utilă în interiorul buclei).b.ReportAllocs()— forțați raportarea alocării chiar și fără-benchmem.
Tabel de referință cu b.Run
La fel ca t.Run pentru teste, există b.Run pentru benchmark-urile parametrice:
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, ",")
}
})
}
}Rânduri de ieșire precum BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ideale pentru scalarea diagramelor.
Compararea a două implementări cu benchstat
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txtbenchstat (în golang.org/x/perf/cmd/benchstat) calculează media, abaterea standard și semnificația statistică a diferenței.
Exerciții
Definiți BenchmarkSum cu bucla peste b.N care apelează Sum(2, 3).
Soluție disponibilă după 3 încercări
Adăugați b.ResetTimer DUPĂ configurarea costisitoare, înainte de buclă, astfel încât configurarea nu este inclusă în măsurare.
Soluție disponibilă după 3 încercări
Care steag rulează toate benchmark-urile din pachet?
$ go test ???