Liveprof mostrará cuándo y por qué ha cambiado el rendimiento de su aplicación PHP



Hola Habr! Mi nombre es Timur Shagiakhmetov, soy desarrollador de PHP en Badoo .

El rendimiento de la aplicación es uno de los criterios más importantes para la calidad del trabajo de un programador. En materia de optimización de aplicaciones PHP, el asistente es el generador de perfiles.

Recientemente, hablamos sobre las herramientas que utilizamos para la creación de perfiles. Permítame recordarle: una de las herramientas para el análisis de rendimiento, cuando no está claro qué partes del código han influido en el aumento del tiempo de generación de respuesta, es XHProf . Esta es una extensión para PHP que le permite perfilar el código en un servidor de combate y luego mejorarlo.

Pero también me gustaría tener un historial de cambios en el rendimiento para que pueda rastrear qué y cuándo se ve afectado su deterioro, ¿verdad? Para hacer esto, hace aproximadamente un año, desarrollamos Liveprof , una herramienta para perfilar automáticamente todas las solicitudes con una interfaz para analizar los cambios en el rendimiento de la aplicación.

Nuestra herramienta le permite analizar el cambio de rendimiento de cualquier parte del código, encontrar los lugares donde más cayó. Al mismo tiempo, no es necesario activarlo específicamente y esperar a que se acumulen las estadísticas; siempre está activo y recopila datos para una cierta fracción de todas las solicitudes.

En este artículo hablaré sobre los detalles de implementación y las características del uso de esta herramienta.

Un poco sobre XHProf


Primero, algunas palabras sobre las características de XHProf. Este es un generador de perfiles para PHP escrito en C como una extensión. Fue desarrollado en Facebook y publicado en el dominio público. Tiene varias horquillas ( uprofiler , Tideways ), totalmente compatibles a nivel del formato de datos de salida.

XHProf establece temporizadores alrededor de todas las llamadas a funciones / métodos. Su uso implica algunos gastos generales. Pero no son tan grandes y permiten usarlo en producción.

El resultado de XHProf es una matriz de elementos en el siguiente formato:

$data = [ 'parentMethodName==>childMethodName' => [ 'ct' => 1 'wt' => 8 'cpu' => 11 'mu' => 528 'pmu' => 0 ] ]; 

donde

parentMethodName y childMethodName son los métodos padre e hijo, respectivamente;
ct : el número de llamadas en el contexto de la solicitud;
wt : tiempo de ejecución de la solicitud (consiste en el tiempo empleado por el procesador y el tiempo de espera para E / S o la respuesta de otro servicio);
cpu : tiempo empleado por el procesador en procesar la solicitud;
mu : cambio en el consumo de memoria después de una llamada al método;
pmu : cambio en el consumo máximo de memoria después de una llamada al método.

Algunas otras opciones también son posibles.

XHProf también contiene herramientas para visualizar los resultados así obtenidos. Para cada operación de creación de perfiles, obtenemos una tabla con un conjunto de parámetros para cada método.

Por ejemplo

resultado de clasificación de burbujas
 <?php class ArrayGenerator { public function getRandomArray(int $count): array { $array = []; for ($i = 0; $i < $count; $i++) { $array[] = rand(0, 1000); } return $array; } } class BubbleSorter { public function sort(&$array): void { $len = count($array); for ($i = 0; $i < $len ; $i++) { for ($j = 0; $j < $len - $i - 1; $j++) { if ($array[$j] > $array[$j + 1]) { $this->swap($array[$j], $array[$j + 1]); } } } } private function swap(&$a, &$b): void { $tmp = $a; $a = $b; $b = $tmp; } public function isSorted(array $array): bool { $len = count($array); for ($i = 0; $i < $len - 1; $i++) { if ($array[$i] > $array[$i + 1]) { return false; } } return true; } } class ArrayPrinter { public function print(array $array, string $delimiter = ' '): void { echo implode($delimiter, $array) . PHP_EOL; } } xhprof_enable(); $n = 10; $arrayGenerator = new \ArrayGenerator(); $array = $arrayGenerator->getRandomArray($n); $sorter = new BubbleSorter(); if (!$sorter->isSorted($array)) { $sorter->sort($array); } $printer = new \ArrayPrinter(); $printer->print($array); $xhprof_data = xhprof_disable(); 




Puede ir dentro de cada método para averiguar qué métodos han utilizado cuántos recursos.

También puede mirar el gráfico de llamadas resaltando los métodos que requieren más recursos:



XHProf es útil para analizar manualmente el rendimiento de cada solicitud. Pero también es importante para nosotros ver el panorama general. Debe comprender cómo ha cambiado el rendimiento con el tiempo. Para hacer esto, se desarrolló una herramienta que perfila consultas en modo automático y le permite analizarlas en la interfaz web.

Liveprof: agregue resultados y mantenga el historial


¿Cómo obtener el historial de perfiles?

Primero debe configurar el inicio automático del generador de perfiles y guardar los resultados. El rendimiento no es constante y fluctúa de un lanzamiento a otro. Para evitar la influencia de tales fluctuaciones, utilizamos los datos promediados de varias consultas. Como resultado, obtenemos resultados agregados para cada consulta, por ejemplo, mínimo, máximo, promedio y percentil 95. Esto ayuda a encontrar cosas difíciles que no se pueden llamar para cada solicitud.

Nuestra herramienta tiene ventajas y algunas limitaciones.

Lo que puede hacer el agregador:


  1. Perfilado automático de cada enésima solicitud.
  2. Agregación diaria de perfiles recopilados.
  3. La capacidad de ver gráficos de cambios en cada parámetro medido por el generador de perfiles. Por ejemplo, wt, cpu, mu, pmu descrito anteriormente.
  4. Vea el cambio en el rendimiento de cualquier método para un determinado intervalo.
  5. Gráfico de llama basado en los últimos datos agregados.
  6. Encuentra consultas que llaman a un método específico

Limitaciones:


  1. Como nuestra herramienta es agregada, no puede averiguar el rendimiento de una consulta (por ejemplo, la más lenta): obtenemos los resultados promediados durante el último día. Pero esto es suficiente para evaluar la dinámica general del rendimiento. Si alguna solicitud se deslizó en la velocidad de ejecución, el valor promedio, el percentil 95 y el tiempo máximo de ejecución cambiarán.
  2. No puede restaurar inequívocamente la pila de llamadas completa, ya que XHProf solo devuelve pares padre-hijo únicos con la suma de los valores de los recursos gastados.
  3. Solicite un error de tiempo de ejecución relacionado con la sobrecarga de XHProf. La diferencia no es tan grande, pero debe tenerse en cuenta al medir el tiempo de ejecución de la consulta.

Cómo usar profiler


  1. Primero, el generador de perfiles debe estar conectado al sitio o script. La forma más conveniente de usar la herramienta es iniciar automáticamente el generador de perfiles :

     php composer.phar require badoo/liveprof # Run a script to configure database LIVE_PROFILER_CONNECTION_URL=mysql://db_user:db_password@db_mysql:3306/Profiler?charset=utf8 php vendor/badoo/liveprof/bin/install.php 

    Es compatible con versiones de PHP que comienzan con 5.4, y su uso está cargado de una sobrecarga mínima, lo que le permite usarlo en un entorno de combate. La herramienta detecta automáticamente la extensión de perfil utilizada: XHProf , uprofiler o Tideways . Al inicio, debe especificar los parámetros para conectarse a la base de datos y la configuración de perfiles.

    Ejemplo de uso en código con configuración predeterminada:

     <?php include 'vendor/autoload.php'; \Badoo\LiveProfiler\LiveProfiler::getInstance()->start(); // Code is here 

    Los resultados del perfil se guardan en la base de datos. Una vez al día, se lleva a cabo un proceso de agregación. Para hacer esto, seleccione todos los registros para una solicitud específica por día y calcule las funciones agregadas para cada uno de los parámetros. Las funciones de agregación se pueden ampliar o redefinir.

    Ahora están disponibles los siguientes:

    • al menos por día;
    • máximo por día;
    • promedio diario
    • Percentil 95 del día.

  2. El cliente web del agregador se utiliza para configurar la agregación y ver los resultados. La forma más fácil de instalarlo en un contenedor acoplable:

     git clone https://github.com/badoo/liveprof-ui.git cd liveprof-ui docker-compose up web 
  3. Antes del primer inicio, debe configurar los parámetros de conexión de la base de datos, una lista de campos y funciones agregadas utilizadas en el archivo de configuración src / config / services.yaml. Luego ejecute el script de instalación:

     docker-compose exec web bash install.sh 
  4. Es necesario registrar automáticamente las secuencias de comandos de agregación y limpieza de datos antiguos en coronas:

     # script aggregates all profiles for previous day, add it if you don't use a queue for aggregation jobs (parameter aggregator.use_jobs_in_aggregation=false) 0 2 * * * docker-compose -f %PATH_TO_PROJECT%/docker-compose.yml run --rm --entrypoint '/usr/local/bin/php /app/bin/cli.php cron:aggregate-all-profiles' web # script removes old aggregated data, by default > 200 days 0 1 * * * docker-compose -f %PATH_TO_PROJECT%/docker-compose.yml run --rm --entrypoint '/usr/local/bin/php /app/bin/cli.php cron:remove-old-profiles' web 200 

  5. Para completar con datos de prueba, puede ejecutar el script:

     docker-compose exec web php /app/bin/cli.php example:a-week-degradation 

Descripción de la interfaz


La interfaz web está disponible en: 127.0.0.1:8000.

Por defecto, se abre una página con una lista de consultas agregadas. Facilita la búsqueda de una consulta de interés, ordena todas las consultas por cualquiera de los parámetros y también vuelve a agregar una consulta específica para ver los últimos resultados:



Una página con una lista de métodos y gráficos de cambios de rendimiento es la más utilizada cuando se trabaja con la herramienta. Le permite pasar por la pila de llamadas, ver el consumo de cada parámetro, así como gráficos de cambios de rendimiento para un determinado intervalo:



Una página con una lista completa de métodos llamados le permite encontrar rápidamente el método de interés y ver los gráficos yendo a la página de gráficos:


La página con el gráfico de llama de la última consulta agregada le permite identificar visualmente las partes más pesadas.

Usar XHProf impone algunas limitaciones en la precisión del resultado. Esto se debe al hecho de que el generador de perfiles no devuelve un árbol de llamadas completo, sino solo los pares padre-hijo. Además, si se llamó a un par de métodos desde diferentes lugares de la aplicación, como resultado obtenemos la cantidad de tiempo invertido. Para un gráfico de llama, debe tener un árbol de llamadas completo. Al restaurar dicho árbol, los valores de los parámetros se normalizan teniendo en cuenta el tiempo dedicado por los padres.


Una página con una lista de métodos que se han vuelto más lentos durante el intervalo seleccionado.

Además, para cada método, puede ver cuáles de las llamadas secundarias afectaron más el rendimiento. Por ejemplo, en la captura de pantalla a continuación, puede ver que el método ServiceApi::getAvailableServices() comenzó a ejecutarse 116 ms más lento. La razón de esto fue la adición de una llamada a ServiceApi::getGifts() (cambio de 56 ms) y un aumento en el número de llamadas al método ServiceApi::getConfigForList() de 1 a 5 (otros 50 ms):



Si no se sabe de antemano qué consulta el rendimiento ha cambiado más notablemente, entonces una página con una lista de métodos que se han vuelto más lentos sin referencia a una consulta específica ayudará:


Una página que busca consultas que invocan un método en particular.

Le permite comparar el tiempo de ejecución en diferentes solicitudes. También es útil para encontrar código no utilizado:



Funciones de personalización


La herramienta tiene amplias oportunidades de personalización:

  • puede agregar sus propias funciones agregadas que calculan un cierto valor en función de la matriz de valores de parámetros aprobada;
  • Puede cambiar la base de datos para almacenar perfiles y resultados agregados (SQLite, MySQL y PostgreSQL ahora son compatibles, pero puede usar otros de la lista disponible para Doctrine DBAL );
  • Puede anular el administrador de conexión de la base de datos e implementar sus métodos para obtener datos;
  • Puede usar la interfaz web tanto como un proyecto independiente como dentro de cualquier marco (por ejemplo, un panel de control del sitio). Un ejemplo:

     public function profileListAction() {      <i>//Some custom logic before</i>   $this->checkPermissions();   $App = new \Badoo\LiveProfilerUI\LiveProfilerUI();   $Page = $App->getPage('profile_method_list_page');   return $Page->setData($data)->render(); } 

Conclusión


Espero que nuestra herramienta sea útil para otros desarrolladores. Permitirá verificar el cambio de rendimiento de cualquier parte del código sin el uso de temporizadores adicionales. También facilitará el proceso de optimización, ya que ahora puede ver lo que afectó la degradación del rendimiento de la aplicación con el tiempo.

Está disponible en GitHub: github.com/badoo/liveprof , la interfaz web es github.com/badoo/liveprof-ui .

La herramienta está en desarrollo activo y puede contener algunos errores. Con suerte, con la participación de la comunidad, mejorará aún más. Los planes incluyen agregar soporte para otros perfiladores además de XHProf, así como expandir la lista de bases de datos compatibles.

Envíenos sus comentarios y preguntas de uso a Telegram , errores y solicitudes de extracción, directamente a GitHub . Agradecemos comentarios y sugerencias!

Un agradecimiento especial a Gregory por la idea y la primera implementación.

Source: https://habr.com/ru/post/es436364/


All Articles