magento
PHP Profiling en Magento 2 con php-spx: workflow para encontrar la causa raíz
Guía de flujo de trabajo para pasar de 'la página está lenta' a causa raíz usando php-spx en Magento 2: Wall vs CPU, Flat Profile, Flame Graph y métricas del Zend Engine.
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.
Ubicación visual sugerida (inicio): coloca aquí la captura general de SPX para contexto.

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.
Ubicación visual sugerida: coloca aquí la captura de Flat Profile.

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.
Ubicación visual sugerida: coloca aquí la captura de Flame Graph.

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.