Direkt zum Hauptinhalt springen
eLearner.app
Modul 9 · Lektion 3 von 543/50 im Kurs~12 min
Lektionen des Moduls (3/5)

Benchmarks und Profile

Neben Funktionstests verfügt go test auch über integrierte Benchmarks (BenchmarkXxx) und unterstützt CPU- und Speicherprofile (pprof). Alles ohne externe Abhängigkeiten.

Form einer Benchmark

Go
func BenchmarkSum(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = Sum(2, 3)
    }
}

Eigenschaften:

  • Genaue Signatur: func BenchmarkXxx(b *testing.B). – Die Schleife muss b.N-Iterationen ausführen: Das Framework passt b.N automatisch an, beginnend bei 1 und ansteigend, bis sich die Messung stabilisiert (standardmäßig ~1 Sekunde).
  • Das Ergebnis ist ns/op (Nanosekunden pro Operation) und mit -benchmem auch B/op und allocs/op.

Typische Befehle

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

Code
BenchmarkSum-8        1000000000        0.31 ns/op

-8 ist der GOMAXPROCS-Wert. 0.31 ns/op ist die durchschnittliche Zeit pro Anruf.

Teures Setup: b.ResetTimer

Wenn Sie vor der Schleife einen langen Vorbereitungsschritt haben, schließen Sie ihn von der Messung aus:

Go
func BenchmarkSearch(b *testing.B) {
    data := buildLargeSlice(1_000_000) // expensive
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        _ = Search(data, 42)
    }
}

Nützliche Varianten:

  • b.StopTimer() / b.StartTimer() – Pausieren Sie die Messung um eine uninteressante Phase herum (praktisch innerhalb der Schleife).
  • b.ReportAllocs() – Zuordnungsberichterstattung auch ohne -benchmem erzwingen.

Benchmark-Tabelle mit b.Run

Genau wie t.Run für Tests gibt es b.Run für 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, ",")
            }
        })
    }
}

Ausgabezeilen wie BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ideal zum Skalieren von Diagrammen.

Vergleich zweier Implementierungen mit 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) berechnet den Mittelwert, die Standardabweichung und die statistische Signifikanz der Differenz.

Übungen

Übung#go.m9.l3.e1
Versuche: 0Wird geladen…

Definieren Sie BenchmarkSum mit der Schleife über b.N, die Sum(2, 3) aufruft.

Editor wird geladen…

Lösung nach 3 Versuchen verfügbar

Übung#go.m9.l3.e2
Versuche: 0Wird geladen…

Fügen Sie b.ResetTimer NACH dem teuren Setup vor der Schleife hinzu, damit das Setup nicht in die Messung einbezogen wird.

Editor wird geladen…

Lösung nach 3 Versuchen verfügbar

Quiz#go.m9.l3.e3
Bereit

Welches Flag führt alle Benchmarks im Paket aus?

Go
$ go test ???
Antwortoptionen