¿Qué es un benchmark en Go?
Un benchmark es una prueba que mide cuánto tiempo tarda una operación en ejecutarse. Go incluye soporte de benchmarks en el mismo paquete testing, sin dependencias externas.

Las funciones de benchmark siguen la convención BenchmarkNombre(b *testing.B):
func BenchmarkSumar(b *testing.B) {
for b.Loop() {
Sumar(2, 3)
}
}
El método b.Loop() es la forma idiomática de escribir benchmarks en Go. El framework controla automáticamente el número de iteraciones hasta obtener una medida estable. Ejecuta con:
go test -bench=. # todos los benchmarks
go test -bench=BenchmarkSumar # uno específico
go test -bench=. -benchtime=5s # ejecutar durante 5 segundos
go test -bench=. -count=3 # repetir 3 veces para estadísticas
Salida de un benchmark
BenchmarkSumar-8 1000000000 0.2895 ns/op
| Campo | Significado |
|-------|-------------|
| BenchmarkSumar-8 | Nombre del benchmark, -8 son los GOMAXPROCS |
| 1000000000 | Iteraciones ejecutadas (b.N) |
| 0.2895 ns/op | Nanosegundos por operación |
Medir asignaciones de memoria: -benchmem
go test -bench=. -benchmem
BenchmarkConcatenar-8 5000000 234 ns/op 64 B/op 2 allocs/op
| Campo | Significado |
|-------|-------------|
| 64 B/op | Bytes asignados por operación |
| 2 allocs/op | Número de asignaciones heap por operación |
Reducir allocs/op es clave para mejorar el rendimiento, ya que menos asignaciones significan menos presión sobre el recolector de basura.
Aislar el código medido: b.ResetTimer y b.StopTimer
Cuando el setup consume tiempo que no debe incluirse en la medición:
func BenchmarkProcesarDatos(b *testing.B) {
// Preparación costosa fuera del bucle
datos := generarDatosGrandes()
b.ResetTimer() // reiniciar el temporizador tras la preparación
for b.Loop() {
ProcesarDatos(datos)
}
}
func BenchmarkConIO(b *testing.B) {
for b.Loop() {
b.StopTimer()
fichero := crearFicheroTemp(b)
b.StartTimer()
LeerFichero(fichero)
}
}
Benchmarks paralelos con b.RunParallel
Para medir rendimiento en escenarios concurrentes:
func BenchmarkHandler(b *testing.B) {
servidor := httptest.NewServer(miHandler())
defer servidor.Close()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
resp, _ := http.Get(servidor.URL + "/api/datos")
resp.Body.Close()
}
})
}
Perfiles con pprof
Para análisis profundo de CPU y memoria:
# Generar perfil de CPU durante benchmarks
go test -bench=. -cpuprofile=cpu.prof
# Generar perfil de memoria
go test -bench=. -memprofile=mem.prof
# Analizar perfiles
go tool pprof cpu.prof
Dentro de la herramienta interactiva:
(pprof) top10 # las 10 funciones que más CPU consumen
(pprof) web # visualización gráfica en el navegador
(pprof) list Funcion # código anotado con tiempos
Comparar benchmarks con benchstat
benchstat detecta diferencias estadísticamente significativas entre dos runs:
go install golang.org/x/perf/cmd/benchstat@latest
# Guardar resultados de dos versiones
go test -bench=. -count=5 > antes.txt
# (hacer cambios en el código)
go test -bench=. -count=5 > despues.txt
benchstat antes.txt despues.txt
Salida ejemplo:
name old time/op new time/op delta
Procesar-8 234ns ± 2% 187ns ± 1% -20.09% (p=0.000 n=5+5)
Optimizaciones comunes detectables con benchmarks
// Mala práctica: concatenación de strings en bucle
func concatenarMal(partes []string) string {
resultado := ""
for _, p := range partes {
resultado += p // nueva asignación en cada iteración
}
return resultado
}
// Buena práctica: usar strings.Builder
func concatenarBien(partes []string) string {
var sb strings.Builder
for _, p := range partes {
sb.WriteString(p)
}
return sb.String()
}
Los benchmarks mostrarán claramente la diferencia en allocs/op.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Go es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Go
Explora más contenido relacionado con Go y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Escribir funciones de benchmark con *testing.B.
- Comprender el ciclo de b.N y su gestión automática por el framework.
- Medir asignaciones de memoria con -benchmem.
- Usar b.ResetTimer y b.StopTimer para aislar el código medido.
- Generar perfiles de CPU y memoria con pprof.
- Comparar benchmarks con benchstat para detectar regresiones.