Passer au contenu principal
eLearner.app
Module 9 · Leçon 3 sur 543/50 dans le cours~12 min
Leçons du module (3/5)

Benchmarks et profils

En plus des tests fonctionnels, go test dispose également de benchmarks intégrés (BenchmarkXxx) et prend en charge les profils de processeur et de mémoire (pprof). Le tout sans dépendances externes.

Forme d'un benchmark

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

Caractéristiques:

  • Signature exacte : func BenchmarkXxx(b *testing.B).
  • La boucle doit exécuter des itérations b.N : le framework ajuste b.N automatiquement, en commençant à 1 et en augmentant jusqu'à ce que la mesure se stabilise (~1 seconde par défaut).
  • Le résultat est ns/op (nanosecondes par opération) et, avec -benchmem, également B/op et allocs/op.

Commandes typiques

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

Sortie typique :

Code
BenchmarkSum-8        1000000000        0.31 ns/op

-8 est la valeur GOMAXPROCS. 0.31 ns/op est la durée moyenne par appel.

Configuration coûteuse : b.ResetTimer

Si vous avez une longue étape de préparation avant la boucle, excluez-la de la mesure :

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

Variantes utiles :

  • b.StopTimer() / b.StartTimer() — pause la mesure autour d'une phase sans intérêt (pratique dans la boucle).
  • b.ReportAllocs() — rapport d'allocation de force même sans -benchmem.

Tableau de référence avec b.Run

Tout comme t.Run pour les tests, il existe b.Run pour les benchmarks paramétriques :

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, ",")
            }
        })
    }
}

Lignes de sortie telles que BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... idéales pour la mise à l'échelle des graphiques.

Comparaison de deux implémentations avec benchstat

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

benchstat (dans golang.org/x/perf/cmd/benchstat) calcule la moyenne, l'écart type et la signification statistique de la différence.

Exercices

Exercice#go.m9.l3.e1
Tentatives : 0Chargement…

Définissez BenchmarkSum avec la boucle sur b.N qui appelle Sum(2, 3).

Chargement de l'éditeur…

Solution disponible après 3 tentatives

Exercice#go.m9.l3.e2
Tentatives : 0Chargement…

Ajoutez b.ResetTimer APRÈS la configuration coûteuse, avant la boucle, afin que la configuration ne soit pas incluse dans la mesure.

Chargement de l'éditeur…

Solution disponible après 3 tentatives

Quiz#go.m9.l3.e3
Prêt

Quel indicateur exécute tous les tests du package ?

Go
$ go test ???
Options de réponse