title: "Conceptos básicos de rendimiento" section: performance-profiling order: 2 tags:
- "go"
- "performance-profiling"
- "basics"
- "performance"
- "benchmarks"
- "pprof" level: basic description: "Aprende los conceptos básicos de rendimiento en Go, incluyendo benchmarks mínimos, estadísticas de asignación con go test -benchmem y testing.B para medir la duración de las funciones." highlights:
- "Usa funciones BenchmarkXxx con b.Loop() para medir ns por operación"
- "Pasa -benchmem para medir bytes y asignaciones por operación"
- "Usa -cpuprofile con go tool pprof para encontrar primero las funciones 'hot'"
- "Usa -memprofile para rastrear el heap en vivo; combínalo con -benchmem para las fuentes"
- "Importa net/http/pprof para registrar endpoints de depuración en localhost"
- "Abre go tool pprof -http para grafos de llama y vistas a nivel de código fuente" updated: "2026-07-18"
Conceptos básicos de rendimiento
9 ejemplos para empezar con el rendimiento: 7 básicos y 2 intermedios.
Prerrequisitos
- Instala Go 1.26.x o posterior desde go.dev/dl.
- Crea un módulo:
mkdir perflab && cd perflab && go mod init example.com/perflab. - Añade un archivo de prueba por ejemplo o un paquete
perflab_test.go. - Opcional:
go install golang.org/x/perf/cmd/benchstat@latestpara comparar ejecuciones de benchmarks.
Ejemplos básicos
1. Benchmark Mínimo
Mide cuánto tiempo tarda una función por iteración con testing.B.
package perflab
import "testing"
func Sum(n int) int {
s := 0
for i := 0; i < n; i++ {
s += i
}
return s
}
func BenchmarkSum(b *testing.B) {
for b.Loop() {
Sum(1000)
}
}go test -bench=BenchmarkSum ./...- Las funciones
BenchmarkXxxviven en archivos*_test.go. b.Loop()(Go 1.24+) reemplaza los bucles manualesb.Ny reinicia los temporizadores correctamente.- La salida muestra
ns/op- nanosegundos por iteración del bucle.
Relacionado: Benchmarks con testing.B y B.Loop - profundidad de los benchmarks
2. Estadísticas de asignación con -benchmem
Informa bytes y asignaciones por operación junto con la temporización.
import "strings"
func BenchmarkJoin(b *testing.B) {
parts := []string{"a", "b", "c", "d"}
b.ReportAllocs()
for b.Loop() {
_ = strings.Join(parts, ",")
}
}go test -bench=BenchmarkJoin -benchmem ./...-benchmemañade las columnasB/op(bytes por operación) yallocs/op(asignaciones por operación).b.ReportAllocs()asegura que las cuentas de asignación aparezcan incluso sin-benchmem.- Un alto número de
allocs/open rutas críticas a menudo importa más que unos pocos nanosegundos.
Relacionado: Preasignación de slices, strings.Builder y predimensionamiento de mapas - reducción de asignaciones
3. Perfil de CPU a partir de un Benchmark
Escribe un archivo de perfil de CPU mientras se ejecutan los benchmarks.
go test -cpuprofile=cpu.prof -bench=BenchmarkJoin ./...
go tool pprof -top cpu.prof-cpuprofiletoma muestras del proceso solo durante el benchmark.go tool pprof -topimprime las funciones más activas ('hot') por tiempo plano de CPU.- Usa esto antes de optimizar: confirma que la función que planeas cambiar es realmente activa.
Relacionado: Perfilado de CPU y Heap con pprof - flujo de trabajo completo de pprof
4. Perfil de Heap a partir de Pruebas
Captura sitios de asignación de heap durante una prueba o benchmark.
go test -memprofile=heap.prof -bench=BenchmarkJoin ./...
go tool pprof -top -alloc_space heap.prof-memprofileregistra muestras de asignación.-alloc_spaceordena por bytes totales asignados;-inuse_spacemuestra el heap en uso.- Combina con
-benchmempara conectar números de micro-optimización con sitios de llamada.
Relacionado: Perfilado de CPU y Heap con pprof - lectura de grafos de heap
5. Endpoint net/http/pprof
Expone perfiles en un servidor HTTP en ejecución para la recopilación de pruebas de carga.
package main
import (
_ "net/http/pprof"
"net/http"
)
func main() {
go func() {
http.ListenAndServe("localhost:6060", nil)
}()
// ... tu servicio en otro puerto
}go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30- La importación
_ "net/http/pprof"registra/debug/pprof/*enDefaultServeMux. - Vincula
6060en localhost o protégelo con autenticación en producción. - Recopila perfiles mientras se ejecutan los generadores de carga, no en un servidor inactivo.
Relacionado: Rendimiento en Go: Medir, Perfilar, Luego Optimizar - cultura de medición
6. Interfaz Web interactiva de pprof
Explora grafos de llama en el navegador.
go tool pprof -http=:8081 cpu.prof- Abre una interfaz web local con vistas de grafo de llama, top, peek y código fuente.
- Usa
FocuseIgnorepara acotar los frames ruidosos de la biblioteca estándar. - Comparte el archivo de perfil en PRs como evidencia de afirmaciones de optimización.
Relacionado: Perfilado de CPU y Heap con pprof - lectura de grafos de llama
7. Rastreo de GC con GODEBUG
Imprime el tiempo del recolector de basura y el tamaño del heap en stderr.
GODEBUG=gctrace=1 go run .- Cada línea registra el ciclo de GC, la pausa y el objetivo del heap.
- Útil cuando los picos de latencia se correlacionan con el GC, no con los puntos calientes de CPU.
- Reduce la tasa de asignación antes de ajustar
GOGCoGOMEMLIMIT.
Relacionado: Ajuste de GC para Servicios Sensibles a la Latencia - experimentos de GC
Ejemplos intermedios
8. Comparar ejecuciones con benchstat
Registra la salida de benchmarks de línea base y candidata, luego compara estadísticamente.
go test -bench=BenchmarkJoin -count=10 ./... > old.txt
# cambia el código
go test -bench=BenchmarkJoin -count=10 ./... > new.txt
benchstat old.txt new.txt-count=10reduce el ruido de la escala de frecuencia de la CPU y el estado de la caché.benchstatinforma si las diferencias son significativas, no solo si son más rápidas en una ejecución.- Documenta el entorno (modelo de CPU,
GOMAXPROCS) al publicar números.
Relacionado: Benchmarks con testing.B y B.Loop - higiene de benchmarks
9. Servidor pprof dedicado con forma de producción
Monta pprof en un mux personalizado con tiempos de espera y enlace a localhost.
package main
import (
"net/http"
_ "net/http/pprof"
"time"
)
func main() {
admin := http.NewServeMux()
admin.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("ok"))
})
// las rutas de pprof se registran en DefaultServeMux; móntalas:
admin.Handle("/debug/", http.DefaultServeMux)
srv := &http.Server{
Addr: "127.0.0.1:6060",
Handler: admin,
ReadHeaderTimeout: 5 * time.Second,
}
_ = srv.ListenAndServe()
}- Un listener de administración separado mantiene los endpoints de depuración fuera del puerto de la API pública.
ReadHeaderTimeoutbloquea ataques slowloris también en el puerto de administración.- En Kubernetes, usa port-forwarding en
6060durante incidentes en lugar de exponerlo públicamente.
Relacionado: Conceptos básicos de net/http - patrones de servidor
Enlaces externos relacionados
- Un Tour de Go - Introducción interactiva oficial a Go.
- Documentación de la Biblioteca Estándar de Go - Referencia completa de la biblioteca estándar.
- Go Playground - Editor y ejecutor online oficial.
- Get Programming with Go (Manning) - Nathan Youngman & Roger Peppé.
- The Go Programming Language (ebook) - Donovan & Kernighan.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, modernizadores go fix - verifica el parche en la compilación), chi (última versión - verifica en la compilación), gin (última versión - verifica en la compilación), echo (última versión - verifica en la compilación), google.golang.org/grpc (última versión - verifica en la compilación), sigs.k8s.io/controller-runtime (última versión - verifica en la compilación), kubebuilder (última versión - verifica en la compilación), tinygo (última versión - verifica los objetivos de placa en la compilación), wazero (última versión - verifica en la compilación) y golangci-lint (última versión - verifica el conjunto de linters en la compilación).