Saltar al contenido principal
eLearner.app
Módulo 9 · Lección 3 de 543/50 en el curso~12 min
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

Go
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 ajusta b.N automá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én B/op y allocs/op.

Comandos típicos

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

Salida típica:

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

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

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

Filas de salida como BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ideales para escalar gráficos.

Comparando dos implementaciones con benchstat

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

benchstat (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

Ejercicio#go.m9.l3.e1
Intentos: 0Cargando...

Defina BenchmarkSum con el bucle sobre b.N que llama Sum(2, 3).

Cargando editor...

Solución disponible después de 3 intentos

Ejercicio#go.m9.l3.e2
Intentos: 0Cargando...

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.

Cargando editor...

Solución disponible después de 3 intentos

Cuestionario#go.m9.l3.e3
Listo

¿Qué bandera ejecuta todos los puntos de referencia del paquete?

Go
$ go test ???
Opciones de respuesta