Volver al blog

Cómo depurar fugas de memoria en Mac con ProcXray

Guía paso a paso para encontrar y corregir fugas de memoria en macOS. Usa los gráficos de memoria en tiempo real y la inspección de procesos de ProcXray para identificar la causa raíz rápidamente.

Las fugas de memoria están entre los errores más frustrantes de diagnosticar: tu app va lenta, el ventilador se acelera y no sabes qué proceso es el culpable ni por qué. Esta guía recorre un enfoque sistemático para encontrar fugas de memoria en macOS con ProcXray.

Respuesta rápida

Para depurar fugas de memoria en macOS, primero confirma un crecimiento sostenido de la memoria que no se recupera, luego identifica el proceso que tiene la fuga, valida el contexto de lanzamiento y el entorno, y correlaciona con señales de descriptores de archivo o de bibliotecas. Usa ProcXray para una clasificación rápida y los perfiladores de cada plataforma para llegar a la causa raíz a nivel de código.

Reconocer los síntomas

Antes de recurrir a una herramienta, confirma que tienes una fuga de memoria y no un uso elevado legítimo:

Paso 1: identificar el proceso que tiene la fuga

Abre ProcXray y ordena por Memory (descendente). Busca:

  1. Un proceso cuya columna de memoria no para de subir
  2. Un proceso con un uso de memoria inesperadamente alto para lo que hace (p. ej., un daemon en segundo plano usando 2 GB)

El gráfico de memoria en tiempo real de ProcXray en la pestaña History del panel de detalles se actualiza continuamente. Fija un proceso sospechoso y observa la línea de tendencia: una fuga se muestra como una pendiente ascendente constante que nunca se aplana.

Paso 2: comprobar qué es realmente el proceso

Haz clic en el proceso sospechoso. En la pestaña General encontrarás:

Un proceso node en segundo plano que devora 3 GB no sirve de nada sin saber que es node /Users/me/myapp/server.js.

Paso 3: inspeccionar las variables de entorno

Cambia a la pestaña Environment. Las fugas de memoria en apps de Node.js, Python o Ruby a veces se deben a una mala configuración del entorno:

Copia el entorno como JSON y revisa los tamaños de caché, los límites de pool o las flags de depuración.

Paso 4: comprobar los descriptores de archivo abiertos

Las fugas de memoria en servidores a menudo van acompañadas de fugas de descriptores de archivo: el proceso abre archivos, sockets o pipes y nunca los cierra. Cambia a la pestaña Connections en ProcXray para ver:

Un servidor con 10 000 descriptores de archivo abiertos cuando debería tener 50 es una señal clara de una fuga de recursos relacionada.

Paso 5: comprobar las bibliotecas cargadas

A veces la fuga está en una biblioteca nativa. La pestaña Modules de ProcXray lista todas las bibliotecas dinámicas que el proceso ha cargado. Compáralas con las dependencias conocidas de tu app: una versión inesperada de una biblioteca, o una que no debería estar ahí en absoluto, puede explicar un comportamiento inusual.

Paso 6: reproducir y confirmar

Una vez que tengas un sospechoso (un proceso concreto + una ruta de código), reproduce la fuga deliberadamente:

  1. Anota la memoria actual del proceso en ProcXray
  2. Desencadena la operación que sospechas que causa la fuga (p. ej., subir un archivo, ejecutar una consulta, llamar a una API)
  3. Observa la tendencia de memoria en ProcXray
  4. Espera a que la app quede inactiva
  5. Si la memoria no vuelve al nivel de partida, has confirmado la ruta de la fuga

Paso 7: análisis en profundidad con herramientas de plataforma

ProcXray te da el qué y el dónde. Para el porqué dentro de tu código, usa herramientas específicas de cada plataforma:

Para apps nativas en Swift/Objective-C:

leaks <PID>          # Apple's built-in leak detector
malloc_history <PID> # Allocation history

O usa el Memory Graph Debugger de Xcode para obtener un árbol de llamadas visual.

Para Node.js:

node --inspect server.js
# Then use Chrome DevTools Memory tab or clinic.js

Para Python:

from memory_profiler import profile
@profile
def my_function():
    ...

Culpables habituales

CausaSeñal
Caché sin límitesLa memoria crece de forma proporcional a las peticiones
Listener de eventos no eliminadoLa memoria crece con las interacciones de la interfaz
Fuga en biblioteca nativaLa pestaña Modules muestra una discrepancia de versión
Descriptores de archivo sin cerrarLa pestaña Connections muestra miles de archivos abiertos
Nodos del DOM retenidosEl proceso del navegador crece pese a navegar a otra página

Resumen

  1. Ordena por memoria en ProcXray e identifica el proceso que crece
  2. Usa la pestaña General para confirmar qué es el proceso y cómo se lanzó
  3. Comprueba las variables de entorno por si hay una mala configuración
  4. Comprueba la pestaña Connections por si hay fugas de descriptores de archivo
  5. Reproduce la ruta de la fuga
  6. Pasa el relevo a Xcode Memory Debugger, clinic.js o memory_profiler para el análisis a nivel de código

Descargar ProcXray → para empezar tu investigación: gratis, macOS Sonoma+.

Preguntas frecuentes

¿Cómo distingo una fuga de memoria de un pico de memoria normal?

Un pico suele estabilizarse o bajar después de que la carga de trabajo termina. Una fuga aparece normalmente como un crecimiento persistente a lo largo de operaciones repetidas, sin volver al nivel de partida durante los periodos de inactividad.

¿Por qué comprobar los descriptores de archivo al depurar fugas de memoria?

Las fugas de recursos suelen darse juntas. Un proceso que abre continuamente sockets o archivos sin cerrarlos puede mostrar tanto crecimiento de descriptores como presión de memoria.

¿Qué herramienta debo usar después de encontrar el proceso que tiene la fuga?

Usa perfiladores específicos del lenguaje o la plataforma: Xcode Memory Graph para Swift/Objective-C, DevTools/clinic.js para Node.js, y flujos de trabajo con memory_profiler o tracemalloc para Python.

Fuentes y referencias