Профилирование PHP7 кода с использованием xhprof



















Со временем любой PHP-программист сталкивается с проблемой низкой производительности своего приложения. Это может быть медленная загрузка конкретной страницы или слишком долгий ответ от API. И порой достаточно сложно понять, в чем причина тормозов? Порой случаются более сложные ситуации: на боевом сервере api сильно тормозит, но на стенде, где происходит разработка, - все хорошо. И пойди разберись, что идет не так. Производить отладку на рабочем сервере - это крайняя степень безысходности, до которой, конечно, лучше не доводить.


Именно для таких ситуаций и были придуманы специальные инструменты, называемые профилировщиками приложений. В мире PHP эту роль выполняют xDebug, а также xhprof. xhprof является более легковесным, простым и гибким инструментом, поэтому его использование более предпочтительно. Что интересно, xhprof был разработан в facebook еще в 2009 году, однако до сих пор от них нет официальной поддержки php7 и больше не будет, поскольку facebook перешел на HHVM. Однако, благодаря обширному сообществу php-разработчиков, появился форк, поддерживающий php7, установка которого не вызывает каких-либо сложностей.



Установка

Для начала нужно, собственно, установить xhprof:


git clone https://github.com/longxinH/xhprof xhprof
cd xhprof/extension
phpize
./configure --with-php-config=/usr/bin/php-config
sudo make && sudo make install
mkdir /var/tmp/xhprof

Далее прописать настройки в php.ini:


[xhprof]
extension=xhprof.so
xhprof.output_dir="/var/tmp/xhprof"

Для папки /var/tmp/xhprof должен быть доступ на запись, т.к. туда будут сохраняться результаты профайлинга.


Можно перезагрузить PHP-FPM и проверить, установилось ли расширение. Банально, это можно сделать с помощью вывода функции phpinfo();


xhprof installed

xhprof установлен, можно им пользоваться. В пакет xhprof входит очень удобный интерфейс для анализа отчетов профилирования. xhprof позволяет строить отчеты, как в текстовом так и графическом виде. В установочной папке xhprof находятся xhprof_html и xhprof_lib, которые нам понадобятся. Папка xhprof_html — предоставляет доступ к GUI. xhprof_lib — библиотека для отображения и анализа кода. Всю папку xhprof целесообразно перенести в /var/www/xhprof и настроить для нее виртуальный хост, например xhprof.loc. Пример для nginx:


server {
listen 80;

server_name xhprof.loc;
charset utf-8;

root /var/www/xhprof/xhprof_html;
index index.php;

location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}

location ~ .php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

Также необходимо не забыть обновить файл hosts. Теперь при введении в браузерe URL xhprof.loc мы будем попадать на веб-интерфейс профилировщика, где будут доступы сгенерированные им файлы.


Теперь можно приступить непосредственно к профилированию кода.


Для включения профилировщика используется функция xhprof_enable(), которая на вход принимает следующие флаги:



  • XHPROF_FLAGS_CPU - для фиксирования статистики процессора;

  • XHPROF_FLAGS_MEMORY — для памяти;

  • XHPROF_FLAGS_NO_BUILTINS — для игнорирования встроенных функций.


Для отключения же профилировщика используется функция xhprof_disable().
Для удобства напишем два скрипта header.php и footer.php, выполняющие эти функции. header.php подключается в начало профилируемого скрипта, а footer.php — в конец. footer.php занимается также и сохранением данных профилирования.


header.php:
if (extension_loaded('xhprof')) {
include_once '/var/www/xhprof/xhprof_lib/utils/xhprof_lib.php';
include_once '/var/www/xhprof/xhprof_lib/utils/xhprof_runs.php';

xhprof_enable(XHPROF_FLAGS_CPU);
}

footer.php:
if (extension_loaded('xhprof')) {
$profilerNamespace = 'ЗДЕСЬ_ИМЯ_ПРОФИЛИРУЕМОГО_СКРИПТА';
$xhprofData = xhprof_disable();
$xhprofRuns = new XHProfRuns_Default();
$runId = $xhprofRuns->save_run($xhprofData, $profilerNamespace);
}


Использование

Подключив header.php и footer.php к профилируемому скриту, можно начинать: при выполнении профилируемого скрипта сгенерируется файл, который сохранится в директории /var/tmp/xhprof, содержащий информацию о работе скрипта. При открытии веб-интерфейса xhprof.loc, будет доступен этот сгенерированный файл:


xhprof profiler

При открытии файла профилирования появляется детальная информация о работе приложения, весь стек вызовов:


xhprof profiling

Что значат столбцы:




  • Calls — количество и процентное соотношение вызовов функции;


  • Incl. Wall Time — время выполнения функции с вложенными функциями;


  • Excl. Wall Time — время выполнения функции без вложенных функций;


  • Incl. CPU — процессорное время с вложенными функциями;


  • Excl. CPU — процессорное время без вложенных функций;


  • Incl. MemUse — потребление памяти с вложенными функциями;


  • Excl. MemUse — потребление памяти без вложенных функций;


  • Incl. PeakMemUse — максимальное потребление памяти с вложенными функциями;


  • Excl. PeakMemUse — максимальное потребление памяти без вложенных функций.


Если перейти по ссылке [View Full Callgraph], то отобразится прекрасное дерево вызовов с визуальной индикацией наиболее тормознутого кода. Если же этого не произошло, то скорее всего нужно установить библиотеку graphviz:


apt-get install graphviz


Пример построенного графика:


xhprof graph vizualization

В моем случае самое узкое место — это взаимодействие с БД.



Использование xhprof на боевом сервере

Изначально xhprof разрабатывался именно с целью профилирования кода в бою, на production серверах. Другого бесплатного и эффективного инструмента профилирования php7-кода в бою по-просту нет, поэтому у xhprof нет конкурентов. Конкретно у меня есть опыт использования xhprof на production сервере, который обрабатывает миллион запросов в сутки. Там используется php7, и проблем пока не было обнаружено. Однако, xhprof не запускается для каждого запроса — генерировалось бы слишком много файлов профилирования. У меня профилировщик запускается только в том случае, если в запросе указан заголовок «XHPROF_ENABLE» и он установлен в true. Также можно использовать и другую стратегию, например, запускать профилировщик случайно с вероятностью, скажем, в 1/1000. Тогда тоже будет достаточно ясная картина.



Вывод

Даже несмотря на то, что xhprof официально не поддерживается для php7, он по-прежнему остается незаменимым инструментом для php-разработчика.








4595   0  

Comments

    Ничего не найдено.