Modulelessen (3/5)
Benchmarks en profielen
Naast functionele tests heeft go test ook ingebouwde benchmarks (BenchmarkXxx) en ondersteunt het CPU- en geheugenprofielen (pprof). Allemaal zonder externe afhankelijkheden.
Vorm van een benchmark
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Sum(2, 3)
}
}Kenmerken:
- Exacte handtekening:
func BenchmarkXxx(b *testing.B). - De lus moet
b.Niteraties uitvoeren: het raamwerk pastb.Nautomatisch aan, beginnend bij 1 en groeit totdat de meting stabiliseert (standaard ~1 seconde). - Het resultaat is
ns/op(nanoseconden per bewerking) en, met-benchmem, ookB/openallocs/op.
Typische commando's
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 profileTypische uitvoer:
BenchmarkSum-8 1000000000 0.31 ns/op
-8 is de GOMAXPROCS waarde. 0.31 ns/op is de gemiddelde tijd per gesprek.
Dure installatie: b.ResetTimer
Als je een lange voorbereidingsstap hebt vóór de lus, sluit deze dan uit van de meting:
func BenchmarkSearch(b *testing.B) {
data := buildLargeSlice(1_000_000) // expensive
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = Search(data, 42)
}
}Handige varianten:
b.StopTimer()/b.StartTimer()— pauzeer de meting rond een oninteressante fase (handig in de lus).b.ReportAllocs()— forceer toewijzingsrapportage, zelfs zonder-benchmem.
Benchmarktabel met b.Run
Net als t.Run voor tests, is er b.Run voor parametrische benchmarks:
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, ",")
}
})
}
}Uitvoerrijen zoals BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ideaal voor schaaldiagrammen.
Vergelijking van twee implementaties met benchstat
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txtbenchstat (in golang.org/x/perf/cmd/benchstat) berekent het gemiddelde, de standaarddeviatie en de statistische significantie van het verschil.
Oefeningen
Definieer BenchmarkSum met de lus over b.N die Sum(2, 3) aanroept.
Oplossing beschikbaar na 3 pogingen
Voeg b.ResetTimer toe NA de dure opstelling, vóór de lus, zodat de opstelling niet wordt meegenomen in de meting.
Oplossing beschikbaar na 3 pogingen
Welke vlag voert alle benchmarks in het pakket uit?
$ go test ???