Perfilado de código Go: encontrando cuellos de botella en la práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: por qué el perfilado de código Go es imprescindible

El desarrollo en Go (Golang) es conocido por su rendimiento y eficiencia. Sin embargo, incluso el código más rápido puede ralentizarse si no se tienen en cuenta las particularidades del manejo de memoria, las gorutinas o la entrada/salida. El perfilado es el proceso de recopilación de datos sobre la ejecución de un programa, que permite mirar «bajo el capó» y comprender qué funciones consumen más CPU, memoria o tiempo.

En este artículo, analizaremos las herramientas prácticas de perfilado en Go: pprof, trace y los benchmarks integrados. Aprenderá a encontrar cuellos de botella y optimizar el código con ejemplos reales.



1. Herramientas principales de perfilado en Golang

Go proporciona un potente arsenal para el perfilado directamente desde su instalación. Consideremos tres enfoques clave:

  • pprof — perfilado de CPU, memoria, bloqueos y gorutinas.
  • trace — trazado de eventos: creación de gorutinas, llamadas al sistema, GC.
  • benchmark — pruebas de rendimiento integradas con go test -bench.

Para empezar a trabajar con pprof, basta con importar net/http/pprof en su servidor HTTP o usar runtime/pprof para aplicaciones CLI.



1.1. Cómo ejecutar el perfilado de CPU

La forma más sencilla es agregar un endpoint a su servidor HTTP:

package main

import ( "log" "net/http" _ "net/http/pprof")

func main() { go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() // su código principal select {}}

Después de ejecutarlo, abra http://localhost:6060/debug/pprof/ — verá un panel. Para recopilar un perfil de CPU durante 30 segundos, ejecute:

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

Esto descargará los datos y abrirá la consola interactiva de pprof.



2. Encontrando cuellos de botella con pprof: CPU y memoria

Supongamos que tenemos una función que procesa un gran conjunto de datos. Sospechamos que está ralentizando el programa. Escribamos un ejemplo de prueba y perfilémoslo.



2.1. Ejemplo de código lento

package main

import ( "fmt" "time")

func slowFunction(data []int) int { sum := 0 for _, v := range data { time.Sleep(1 * time.Microsecond) // simulación de trabajo sum += v * v } return sum}

func main() { data := make([]int, 100000) for i := range data { data[i] = i } result := slowFunction(data) fmt.Println(result)}

Ejecutemos el perfilado de CPU:

go run main.go &go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=10

En el navegador se abrirá una visualización: un grafo de llamadas (call graph). El grosor de las aristas muestra cuánto tiempo tomó cada función. Veremos inmediatamente que slowFunction y time.Sleep son los principales consumidores de CPU.



2.2. Análisis de memoria (heap profile)

Para encontrar fugas de memoria u objetos que ocupan demasiado espacio, use:

go tool pprof http://localhost:6060/debug/pprof/heap

En la consola interactiva puede ejecutar el comando top:

(pprof) top10Showing nodes accounting for 80MB, 100% of 80MB total      flat  flat%   sum%        cum   cum%      40MB 50.00% 50.00%       40MB 50.00%  main.slowFunction      20MB 25.00% 75.00%       20MB 25.00%  main.createLargeSlice      20MB 25.00% 100.00%      20MB 25.00%  runtime.makeslice

Esto muestra qué funciones asignan más memoria. Si ve que main.slowFunction asigna 40MB, debería considerar una refactorización, por ejemplo, usar la reutilización de slices.

Blogs

Book Recommendations