SymfonyWorld Online 2020
100% online
30+ talks + workshops
Live + Replay watch talks later

Paso 30: Descubriendo el corazón de Symfony

5.0 version
Maintained

Descubriendo el corazón de Symfony

Hemos estado usando Symfony durante un tiempo para desarrollar una poderosa aplicación, pero la mayor parte del código ejecutado por la aplicación proviene de Symfony. Cientos de líneas de código frente a miles de ellas.

Me gusta entender cómo funcionan las cosas detrás de bastidores. Y siempre me han fascinado las herramientas que me ayudan a entender cómo funcionan las cosas. La primera vez que usé un depurador paso a paso o la primera vez que descubrí ptrace son recuerdos mágicos.

¿Te gustaría entender mejor cómo funciona Symfony? Es hora de indagar en cómo Symfony hace funcionar tu aplicación. En lugar de describir cómo Symfony maneja una petición HTTP desde una perspectiva teórica, lo que sería bastante aburrido, vamos a utilizar Blackfire para obtener algunas representaciones visuales y utilizarlo para descubrir algunos temas más avanzados.

Entendiendo el corazón de Symfony con Blackfire

Ya sabes que todas las peticiones HTTP se sirven por un único punto de entrada: el archivo public/index.php. Pero ¿qué pasa después? ¿cómo se llama a los controladores?

Hagamos un perfil en producción de la página de inicio en inglés con Blackfire a través de la extensión del navegador Blackfire:

1
$ symfony remote:open

O directamente a través de la línea de comandos:

1
$ blackfire curl `symfony env:urls --first`en/

Dirígete a la vista «Timeline» (línea de tiempo) del perfil, deberías ver algo similar a lo siguiente:

Desde la línea de tiempo, pasa el puntero del ratón por las barras de color para tener más información sobre cada llamada; aprenderás mucho sobre cómo funciona Symfony:

  • El punto de entrada principal es public/index.php;
  • El método Kernel::handle() gestiona la solicitud;
  • Llama al HttpKernel que dispara algunos eventos;
  • El primer evento es RequestEvent;
  • El método ControllerResolver::getController() se invoca para determinar qué controlador se debería llamar para la URL entrante;
  • El método ControllerResolver::getArguments() se invoca para determinar qué argumentos pasar al controlador (se llama al convertidor de parámetros);
  • El método ConferenceController::index() se invoca ahora, con lo que la mayor parte de nuestro código es ejecutado por esta llamada;
  • El método ConferenceRepository::findAll() obtiene todas las conferencias de la base de datos (observa la conexión a la base de datos vía PDO::__construct());
  • El método Twig\Environment::render() renderiza la plantilla;
  • Los eventos ResponseEvent y FinishRequestEvent se disparan, aunque da la sensación de que no hay oyentes (listeners) registrados, ya que parecen ser muy rápidos en su ejecución.

La línea de tiempo es una forma excelente de entender cómo funciona parte del código; esto es especialmente útil cuando te enfrentas a un proyecto desarrollado por otra persona.

Ahora, genera un perfil de la misma página desde la máquina local en el entorno de desarrollo:

1
$ blackfire curl `symfony var:export SYMFONY_DEFAULT_ROUTE_URL`en/

Abre el perfil. Deberías ser redirigido a la vista del gráfico de llamadas ya que la solicitud fue muy rápida y la línea de tiempo estará bastante vacía:

¿Entiendes lo que está pasando? La caché HTTP está habilitada y como tal, estamos analizando la capa de caché HTTP de Symfony. Como la página está en la caché, HttpCache\Store::restoreResponse() está obteniendo la respuesta HTTP de su caché y nunca se llama al controlador.

Deshabilita la capa de caché en public/index.php como hicimos en el paso anterior e inténtalo de nuevo. Puedes ver inmediatamente que el perfil se ve muy diferente:

Las principales diferencias son las siguientes:

  • El TerminateEvent, que no era visible en producción, toma un gran porcentaje del tiempo de ejecución; mirando más de cerca, se puede ver que este es el evento responsable de almacenar los datos del Symfony profiler recopilados durante la solicitud;
  • Bajo la llamada ConferenceController::index(), observa el método SubRequestHandler::handle() que crea el ESI (es por eso que tenemos dos llamadas a Profiler::saveProfile(), una para la solicitud principal y otra para el ESI).

Explora la línea de tiempo para obtener más información; cambia a la vista del gráfico de llamadas para tener una representación diferente de los mismos datos.

Como acabamos de descubrir, el código ejecutado en desarrollo y producción es bastante diferente. El entorno de desarrollo es más lento ya que Symfony Profiler intenta recopilar muchos datos para facilitar la depuración. Es por eso que siempre debes hacer un perfil con el entorno de producción, incluso en local.

Algunos experimentos interesantes: analizar una página de error, analizar la página / (que es un redireccionamiento), o un recurso de la API. Cada perfil te dirá un poco más sobre cómo funciona Symfony, qué clase/métodos se llaman, qué es caro de ejecutar y qué es barato.

Usando el complemento de depuración de Blackfire

Por defecto, Blackfire elimina todas las llamadas a métodos que no son lo suficientemente significativas para evitar tener grandes cargas y grandes gráficos. Cuando se utiliza Blackfire como herramienta de depuración, es mejor mantener todas las llamadas. Esto es proporcionado por el complemento de depuración.

Desde la línea de comandos, utiliza el parámetro --debug:

1
2
$ blackfire --debug curl `symfony var:export SYMFONY_DEFAULT_ROUTE_URL`en/
$ blackfire --debug curl `symfony env:urls --first`en/

En producción, verías, por ejemplo, que se carga un archivo llamado .env.local.php:

¿De dónde viene? SymfonyCloud hace algunas optimizaciones cuando despliega una aplicación Symfony, como optimizar el Composer autoloader (--optimize-autoloader --apcu-autoloader --classmap-authoritative). También optimiza las variables de entorno definidas en el archivo .env (para evitar el análisis del archivo para cada solicitud) mediante la generación del archivo .env.local.prod:

1
$ symfony run composer dump-env prod

Blackfire es una herramienta muy poderosa que ayuda a entender cómo es ejecutado el código por PHP. Mejorar el rendimiento es sólo una de las ventajas de usar un profiler.


This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.