Direct naar de hoofdinhoud
Module 9 · Les 3 van 543/50 in de cursus~12 min
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

Go
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.N iteraties uitvoeren: het raamwerk past b.N automatisch aan, beginnend bij 1 en groeit totdat de meting stabiliseert (standaard ~1 seconde).
  • Het resultaat is ns/op (nanoseconden per bewerking) en, met -benchmem, ook B/op en allocs/op.

Typische commando's

Bash
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 profile

Typische uitvoer:

Code
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:

Go
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:

Go
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

Bash
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txt

benchstat (in golang.org/x/perf/cmd/benchstat) berekent het gemiddelde, de standaarddeviatie en de statistische significantie van het verschil.

Oefeningen

Oefening#go.m9.l3.e1
Pogingen: 0Laden…

Definieer BenchmarkSum met de lus over b.N die Sum(2, 3) aanroept.

Editor laden…

Oplossing beschikbaar na 3 pogingen

Oefening#go.m9.l3.e2
Pogingen: 0Laden…

Voeg b.ResetTimer toe NA de dure opstelling, vóór de lus, zodat de opstelling niet wordt meegenomen in de meting.

Editor laden…

Oplossing beschikbaar na 3 pogingen

Quiz#go.m9.l3.e3
Klaar

Welke vlag voert alle benchmarks in het pakket uit?

Go
$ go test ???
Antwoordmogelijkheden