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
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 ajusteb.Nautomatiquement, 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, égalementB/opetallocs/op.
Commandes typiques
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 profileSortie typique :
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 :
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 :
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
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txtbenchstat (dans golang.org/x/perf/cmd/benchstat) calcule la moyenne, l'écart type et la signification statistique de la différence.
Exercices
Définissez BenchmarkSum avec la boucle sur b.N qui appelle Sum(2, 3).
Solution disponible après 3 tentatives
Ajoutez b.ResetTimer APRÈS la configuration coûteuse, avant la boucle, afin que la configuration ne soit pas incluse dans la mesure.
Solution disponible après 3 tentatives
Quel indicateur exécute tous les tests du package ?
$ go test ???