magentoPHP Profiling en Magento 2 con php-spx: workflow para encontrar la causa raíz
PHP Profiling en Magento 2 con php-spx
Guía de flujo de trabajo: de lentitud a causa raíz
Introducción
No optimices a ojo. En Magento 2 eso casi siempre termina en cambios caros con poco impacto.
Cuando notes lentitud, sigue este flujo: medir -> aislar -> explicar -> corregir.

Quick Start
Quieres datos rápido. Haz una corrida de profiling antes de tocar código.
En Warden, SPX ya viene dentro de las imágenes de PHP: es un superpoder dormido que solo hay que encender.
- Activa SPX en tu
.env:WARDEN_PHP_SPX=1
- Aplica cambios en los contenedores:
warden env up -d
- Abre tu sitio Magento y el panel de SPX por Traefik:
- app:
https://yourdomain.test - panel:
https://spx.yourdomain.test
- app:
- En el panel, activa captura automática cuando necesites cazar lentitud intermitente (ideal para llamadas AJAX en Magento).
- Repite 2-3 veces el mismo flujo para evitar falsos positivos por warmup.
Profiling por CLI en Warden (bin/magento)
También puedes perfilar comandos de consola para detectar cuellos fuera del request HTTP.
- Entra al contenedor PHP:
warden shell
- Ejecuta el comando con SPX habilitado:
SPX_ENABLED=1 bin/magento <comando>
- Revisa el resultado en
https://spx.yourdomain.testy compara runs similares.
Pro Tip: perfila con cache warm y cache cold por separado. Los patrones cambian mucho en Magento.
Fase 1: Diagnóstico de Superficie (Wall Time vs CPU Time)
Este es siempre el primer paso.
- Wall Time: tiempo real total (incluye esperas de DB, disco, red).
- CPU Time: tiempo real de ejecución de CPU en PHP.
Lógica Si/Entonces
- Si Wall Time es alto y CPU Time es bajo: el cuello está fuera del CPU PHP.
- Revisa DB lenta, locking, Redis, filesystem, HTTP externo, DNS.
- Si Wall Time y CPU Time son altos: el problema está en código PHP/arquitectura.
- Revisa loops, N+1, repositorios llamados en cascada, observers/plugins excesivos.
En Magento 2, este filtro te evita perder horas optimizando código cuando el problema real era query/I/O.
Pro Tip: si ves
ProductRepository::getById()cientos de veces en una sola request, sospecha N+1 de catálogo inmediatamente.
Fase 2: Identificando al Culpable (Flat Profile)
Con el diagnóstico de superficie listo, pasa a identificar qué función consume tiempo.

El Flat Profile ordena funciones por costo. Aquí decides qué optimizar primero.
Qué mirar
- Exclusive Time: tiempo propio de la función (su lógica interna).
- Inclusive Time: tiempo de la función + todo lo que llama.
- Calls: cantidad de invocaciones.
Decisión práctica
- Exclusive alto -> esa función es el problema directo.
- Inclusive alto + Exclusive bajo -> el problema está en funciones hijas.
- Calls alto -> posible problema de diseño (N+1, loops, falta de memoización/cache).
Ejemplos típicos en Magento:
Magento\Catalog\Model\ProductRepository::getByIdMagento\Framework\Event\Manager::dispatchMagento\Framework\Interception\PluginList(cadenas de plugins)
Pro Tip: prioriza primero funciones con alto impacto total (inclusive + calls), no solo la más lenta por ejecución individual.
Fase 3: Entendiendo el Contexto (Flame Graph)
Ya sabes el culpable principal. Ahora necesitas el contexto de ejecución.

El Flame Graph muestra el stack visual:
- ancho = costo en tiempo
- altura = profundidad de llamadas
Qué buscar en Magento
- Bloques anchos repetidos: misma operación invocada desde muchos lugares.
- Jerarquías muy profundas: exceso de capas (plugins/observers/interceptores).
- Ramas paralelas similares: patrón duplicado en layout blocks/view models.
Aquí detectas patrones de diseño ineficientes, no solo funciones lentas.
Pro Tip: si una función aparece en muchos caminos del gráfico, no la optimices localmente: corrige el punto de orquestación que la dispara.
Fase 4: El Deep Dive (Métricas del Zend Engine & I/O)
Esta es la investigación forense. Ahora respondes por qué esa función/ruta es lenta.
Usa estas métricas cuando ya identificaste el hotspot en Fase 2.
Memoria y objetos
- Allocated bytes / allocation count: presión de memoria.
- Free count / freed bytes: ritmo de liberación.
- Process RSS: memoria real del proceso.
Interpretación:
- Si suben allocations + RSS: exceso de objetos/arrays temporales.
- En Magento, suele pasar con colecciones grandes, hydration innecesaria y transformaciones repetidas.
Garbage Collector (GC)
- GC root buffer length
- GC collected cycle count
Interpretación:
- GC muy activo = demasiada rotación de objetos.
- Revisa factories/DTOs creados dentro de loops y conversiones redundantes.
Includes, funciones y opcodes
- Included files / executed lines
- User classes/functions/objects
- Opcode count
Interpretación:
- picos de includes/clases en una request puntual suelen indicar módulos/código ejecutándose sin necesidad.
I/O
- I/O read bytes / write bytes
Interpretación:
- I/O alto con CPU bajo = espera externa clara.
- Revisa logs excesivos, lecturas de disco, sesiones, integraciones, cache backend.
Pro Tip: en Adobe Commerce, un Event/Observer que serializa payloads grandes puede disparar CPU + memoria + I/O al mismo tiempo.
Conclusión y Performance Cheat Sheet
Flujo recomendado:
- Wall vs CPU para clasificar el tipo de problema.
- Flat Profile para encontrar la función ofensora.
- Flame Graph para entender contexto y diseño.
- Zend/I/O para explicar la causa técnica exacta.
Performance Cheat Sheet
| Síntoma observado | Métrica SPX a revisar | Lectura probable | Acción inicial |
|---|---|---|---|
| Página lenta, CPU baja | Wall Time alto + CPU Time bajo | Espera externa (DB/I/O/red) | Revisar queries, Redis, FS, APIs |
| CPU disparada | CPU Time alto | Código PHP pesado | Revisar loops y cálculos redundantes |
| Función "inocente" aparece arriba | Inclusive alto, Exclusive bajo | Costo heredado de hijas | Bajar por stack y aislar subllamada |
| Mucha memoria consumida | Allocated Bytes + RSS | Exceso de objetos/datos | Reducir hydration, paginar, lazy-load |
| GC muy activo | GC root buffer / collected cycles | Demasiados objetos temporales | Evitar creación de objetos en loops |
| Llamadas repetidas | Calls alto en Flat Profile | N+1 / diseño repetitivo | Cache local, batch (getList), refactor de flujo |
| Jerarquía profunda | Flame Graph alto/profundo | Cadena compleja (plugins/observers) | Simplificar puntos de extensión |
| Disco/red saturado | I/O read/write alto | Cuello en I/O | Reducir escrituras y dependencias externas |
| Profiling falla por memoria | Run incompleto + RSS/Allocated Bytes al límite | Límite de memoria bajo en entorno local | Subir WARDEN_PHP_MEMORY_LIMIT en .env y ejecutar warden env up -d |
Si quieres performance real en Magento 2: mide primero, optimiza después.
