Lecciones del módulo (3/5)
Benchmarks y perfiles
Además de las pruebas funcionales, go test también tiene puntos de referencia integrados (BenchmarkXxx) y admite perfiles de CPU y memoria (pprof). Todo sin dependencias externas.
Forma de un punto de referencia
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = Sum(2, 3)
}
}Características:
- Firma exacta:
func BenchmarkXxx(b *testing.B). - El bucle debe ejecutar iteraciones
b.N: el marco ajustab.Nautomáticamente, comenzando en 1 y creciendo hasta que la medición se estabiliza (~1 segundo por defecto). - El resultado es
ns/op(nanosegundos por operación) y, con-benchmem, tambiénB/opyallocs/op.
Comandos típicos
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 profileSalida típica:
BenchmarkSum-8 1000000000 0.31 ns/op
-8 es el valor de GOMAXPROCS. 0.31 ns/op es el tiempo promedio por llamada.
Configuración costosa: b.ResetTimer
Si tiene un paso de preparación largo antes del bucle, exclúyalo de la medición:
func BenchmarkSearch(b *testing.B) {
data := buildLargeSlice(1_000_000) // expensive
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = Search(data, 42)
}
}Variantes útiles:
b.StopTimer()/b.StartTimer(): pausa la medición alrededor de una fase que no es interesante (útil dentro del bucle).b.ReportAllocs(): informe de asignación de fuerza incluso sin-benchmem.
Tabla de referencia con b.Run
Al igual que t.Run para pruebas, existe b.Run para pruebas comparativas paramétricas:
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, ",")
}
})
}
}Filas de salida como BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ideales para escalar gráficos.
Comparando dos implementaciones con benchstat
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txtbenchstat (en golang.org/x/perf/cmd/benchstat) calcula la media, la desviación estándar y la significación estadística de la diferencia.
Ejercicios
Defina BenchmarkSum con el bucle sobre b.N que llama Sum(2, 3).
Solución disponible después de 3 intentos
Agregue b.ResetTimer DESPUÉS de la costosa configuración, antes del ciclo, para que la configuración no esté incluida en la medición.
Solución disponible después de 3 intentos
¿Qué bandera ejecuta todos los puntos de referencia del paquete?
$ go test ???