El módulo tracemalloc rastrea asignaciones de memoria realizadas por Python y registra dónde ocurrieron. Permite medir memoria actual y pico, crear snapshots, agrupar asignaciones por archivo o línea, comparar estados y aplicar filtros. Es una herramienta importante para investigar crecimiento de memoria, caches sin límite, estructuras retenidas por error y regresiones entre versiones.
tracemalloc no mide toda la memoria residente del proceso. Bibliotecas nativas, buffers externos, memoria del sistema operativo, GPU y asignaciones que no pasan por los allocators rastreados pueden quedar fuera. Combínalo con métricas RSS, herramientas del sistema y conocimiento del workload.
Inicia el rastreo
Llama start() antes del código que quieres observar.
import tracemalloc
tracemalloc.start()
ejecutar_aplicacion()
Iniciar temprano captura imports e inicialización; iniciar más tarde reduce ruido y overhead.
Profundidad de frames
start(nframe) define cuántos frames de traceback se guardan por asignación.
tracemalloc.start(10)
Más frames mejoran la atribución, pero aumentan consumo y coste.
Comprueba si está activo
is_tracing() informa el estado global.
if not tracemalloc.is_tracing():
tracemalloc.start(5)
Una biblioteca no debería iniciar o detener el tracing global sin documentar su impacto.
Memoria actual y pico
get_traced_memory() devuelve bytes actuales y pico rastreados.
actual, pico = tracemalloc.get_traced_memory()
print(actual, pico)
El pico revela una operación temporalmente costosa aunque la memoria sea liberada después.
Resetea el pico
reset_peak() redefine el máximo sin borrar las asignaciones actuales.
tracemalloc.reset_peak()
ejecutar_etapa()
actual, pico_etapa = tracemalloc.get_traced_memory()
Esto permite medir picos por fase.
Crea un snapshot
take_snapshot() captura las asignaciones rastreadas en un instante.
snapshot = tracemalloc.take_snapshot()
Los snapshots consumen memoria. No los crees continuamente en producción sin límites.
Estadísticas por línea
statistics("lineno") agrupa asignaciones por línea.
for estadistica in snapshot.statistics("lineno")[:10]:
print(estadistica)
Observa tamaño total, cantidad y media. Muchas asignaciones pequeñas pueden ser tan importantes como una grande.
Agrupa por archivo o traceback
Usa filename para archivo y traceback para diferenciar caminos de llamada.
top = snapshot.statistics("traceback")[:5]
for item in top:
print(item.size, item.count)
for frame in item.traceback.format():
print(frame)
El agrupamiento por traceback es detallado y puede generar muchos grupos.
Compara snapshots
Una comparación muestra crecimiento y reducción entre dos estados.
antes = tracemalloc.take_snapshot()
ejecutar_escenario()
despues = tracemalloc.take_snapshot()
for diferencia in despues.compare_to(antes, "lineno")[:10]:
print(diferencia)
Repite el escenario para separar warm-up de crecimiento continuo.
Baseline después del warm-up
Imports, caches de bytecode, pools e inicialización lazy crean asignaciones legítimas.
Ejecuta una fase de calentamiento y captura la referencia cuando el sistema esté estable.
Detecta crecimiento repetido
for _ in range(5):
ejecutar_escenario()
gc.collect()
snapshot = tracemalloc.take_snapshot()
registrar(snapshot)
gc.collect() puede reducir ruido de diagnóstico, pero no representa necesariamente producción.
Filtros
Filter y DomainFilter incluyen o excluyen traces.
filtros = [
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "*/site-packages/*"),
]
filtrado = snapshot.filter_traces(filtros)
No filtres dependencias demasiado pronto; pueden ser el origen real.
Filtros inclusivos y exclusivos
Un filtro exclusivo elimina coincidencias y uno inclusivo conserva solo las compatibles.
Documenta patrones para que el informe sea reproducible.
Tracebacks de asignación
Las APIs de trace permiten inspeccionar frames registrados para bloques individuales.
Las estadísticas agregadas suelen ser más útiles que listar millones de traces.
Guarda y carga snapshots
Los snapshots pueden persistirse.
snapshot.dump("memoria.snap")
cargado = tracemalloc.Snapshot.load("memoria.snap")
El archivo puede revelar paths y nombres internos. Protégelo como artefacto de diagnóstico.
Usa linecache en informes
Recupera el código fuente para enriquecer la salida.
import linecache
frame = estadistica.traceback[0]
linea = linecache.getline(frame.filename, frame.lineno).strip()
Consulta linecache en Python.
Inicia antes de imports
Opciones del intérprete o una variable de entorno pueden activar tracing antes del código de aplicación.
Ayuda con startup, pero produce más ruido.
Overhead
Guardar tracebacks consume CPU y memoria. El coste crece con la cantidad de frames.
En producción, usa ventanas cortas, una instancia de diagnóstico o un procedimiento controlado.
Memoria rastreada frente a RSS
RSS puede continuar alto después de liberar objetos porque allocators conservan arenas y el sistema administra páginas.
Una caída en bytes rastreados sin caída de RSS no prueba un leak. Analiza tendencias.
Memoria nativa
NumPy, imágenes, compresión, drivers y extensiones C pueden asignar fuera de los dominios visibles.
Si RSS crece y tracemalloc permanece estable, usa profilers nativos y métricas específicas.
Objetos vivos y referencias
tracemalloc muestra dónde se asignó memoria, no necesariamente por qué el objeto sigue vivo.
Combínalo con gc, inspección de referencias y análisis de caches.
Leaks frente a caches
Un cache puede crecer por diseño, pero sin límite se convierte en leak operacional.
Revisa tamaño máximo, expiración, cardinalidad de claves y eviction.
Threads
El tracing es global al proceso. Las asignaciones de varias threads aparecen en los mismos snapshots.
Sincroniza el escenario para comparar fases equivalentes.
Procesos
Cada proceso posee su propio estado de tracemalloc.
En multiprocessing, recopila snapshots o métricas por worker y agrega externamente. No confundas un worker con el total del servicio.
Tests de regresión
Un test puede repetir un escenario y verificar que el crecimiento neto quede bajo un margen.
Evita límites rígidos: versión de Python, plataforma e imports cambian números exactos. Usa tendencias y tolerancia.
Mide una función
def medir(funcion, *args, **kwargs):
tracemalloc.start(10)
try:
tracemalloc.reset_peak()
resultado = funcion(*args, **kwargs)
actual, pico = tracemalloc.get_traced_memory()
return resultado, actual, pico
finally:
tracemalloc.stop()
No detengas un tracing que pertenece a otro componente.
clear_traces
clear_traces() elimina traces registrados sin cambiar objetos vivos.
Úsalo para iniciar una fase limpia, sabiendo que pierdes el historial anterior.
stop
stop() desactiva el rastreo y limpia estado interno según la versión.
Los snapshots ya creados pueden seguir analizándose.
Informes útiles
Incluye archivo, línea, fuente, tamaño, diferencia, cantidad y media. Muestra unidades legibles, pero conserva bytes para cálculos.
Destaca los mayores crecimientos en vez de mostrar miles de entradas.
Seguridad y privacidad
Paths y líneas pueden revelar nombres de clientes, directorios internos y lógica propietaria.
Redacta datos antes de adjuntar informes a tickets públicos.
Observabilidad
tracemalloc es principalmente una herramienta de diagnóstico, no una métrica continua de alta frecuencia.
Monitoriza RSS, contadores de objetos y caches; activa snapshots cuando las tendencias indiquen problema.
Pruebas
Prueba un escenario estable, crecimiento intencional, liberación, cache limitado, varias threads y procesos separados.
Controla warm-up, usa entrada determinística y repite para reducir ruido.
Errores comunes
Los fallos frecuentes son confundir memoria rastreada con RSS, capturar baseline antes del warm-up, usar un solo snapshot, filtrar dependencias pronto, ignorar memoria nativa, guardar demasiados frames en producción y asumir que todo crecimiento es leak.
Conclusión
tracemalloc muestra dónde Python asigna memoria y cómo cambia el perfil. Usa snapshots comparables, filtros documentados, picos por fase y escenarios repetidos.
Combina resultados con RSS, garbage collector y métricas nativas. Consulta la documentación oficial de tracemalloc, linecache en Python y la guía para detectar fugas de memoria.







