XHProf и xDebug - профилирование (profiling) кода PHP
С помощью систем для профилирования можно собрать информацию о том, какие функции в php-коде потребляют больше процессорного времени и оперативной памяти, то есть выявить наиболее медленные и требовательные к памяти места в программе на php.
xhprof
XHProf - PHP profiler разработанный в Facebook.
Установка:
aptitude install php-pear pecl install xhprof-0.9.4 echo "extension=xhprof.so" > /etc/php5/mods-available/xhprof.ini ln -s /etc/php5/mods-available/xhprof.ini /etc/php5/conf.d/xhprof.ini apachectl restart
Необходимые для работы файлы расположены в директории /usr/share/php. Однако не все, а только c php-кодом. Для нормального отображения отчетов требуется jquery и css. Их можно заполучить из репозитория на github:
git clone https://github.com/facebook/xhprof.git
Далее, для сбора данных требуется скопировать директорию xhprof_lib в директорию сайта. Выше уже сообщалось, что данные файлы расположены в директории /usr/share/php.
После этого в код php-скрипта в месте, откуда должен начаться сбор данных добавляем строку:
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
В скобках указаны параметры для сбора данных. В данном случае будет осуществляться сбор данных по нагрузке на процессор и по использованию оперативной памяти. Возможен еще один параметр XHPROF_FLAGS_NO_BUILTINS при использовании которого данные по встроенным функциям не собираются.
Далее, в конце php-кода, который будет профилироваться следует добавить:
$xhprof_data = xhprof_disable(); include_once "xhprof_lib/utils/xhprof_lib.php"; include_once "xhprof_lib/utils/xhprof_runs.php"; $xhprof_runs = new XHProfRuns_Default(); $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_test"); echo "Report: http://domain.tld/xhprof_html/index.php?run=$run_id&source=xhprof_test"; echo "\n";
В строке $run_id в кавычках указано название профиля, которое можно задать произвольно.
Название профиля используется в ссылке на страницу с отображением содержимого профиля, которая будет видна на профилируемой странице и которую можно будет скопировать в строку адреса браузера.
По ссылке вида http://domain.tld/xhprof_html/ можно будет получить список адресов на страницы с информацией по созданным ранее профилям.
Результат в обработанном виде выглядит следующим образом:
Щелкая по ссылкам можно углубиться в цепочки вызовов функций с аналогичной информацией на каждом этапе.
Если указать параметр XHPROF_FLAGS_NO_BUILTINS, то видно, что количество вызовов функций значительно снижается:
В таблице представлена следующая информация:
Calls - количество вызовов функции,
Wall Time - общее время работы функции вклчая время ожидания ответа от внешних ресурсов,
CPU - сколько времени было затарчено на обработку функций,
MemUse - сколько оперативной памяти было задействовано,
PeakMemUse - пиковое потребление памяти.
В качестве модификаторов выступают:
Incl - inclusive - с учетом вызовов других функций из этой функции,
Excl - exclusive - без учета вызовов функций.
Кроме того, над таблицей представлена информация о суммарных времени обработки, использованной памяти и количестве вызовов функций.
Также XHProf позволяет строить разностные отчеты между двумя запусками, которые обозначаются красным и зеленым цветами. С помощью таких отчетов можно получить ясную картину улучшений после каждого изменения кода.
Для получения подобного отчета нужно воспользоваться ссылкой вида:
http://domain.tld/xhprof_html/index.php?run1=run_id1&run2=run_id2&source=xhprof_test
где run_id1 и run_id2 - идентификаторы запусков.
Если установить Graphviz:
aptitude install graphviz
то по ссылке “View Full Callgraph” откроется наглядная схема на которой будут обозначены наиболее долгие вызовы функций и их место в цепочке вызовов:
Также для php profiler xhprof существуют сторонние веб-интерфейсы использующие базы данных:
http://xhprof.io/ - MySQL,
https://github.com/perftools/xhgui - MongoDB.
xDebug
xDebug - дебаггер PHP-кода с возможностью профилирования (profiling), написанный Дериком Ретансом (Derick Rethans).
Установка:
yum install php5-xdebug
Затем редактируем конфиг:
nano /etc/php5/mods-available/xdebug.ini
добавляя в него строки:
xdebug.profiler_enable = 1 xdebug.profiler_aggregate = On xdebug.profiler_output_dir = /tmp
Здесь включаем PHP профайлер и указываем директорию в которую складывать профили. Профили создаются с именами вида cachegrind.out.*
Существует веб-клиент webgrind: https://github.com/jokkedk/webgrind. Работает он не слишком быстро, но позволяет оперативно просмотреть небольшие профили. Фактически это код на PHP, который нужно склонировать с github:
git clone https://github.com/jokkedk/webgrind.git
создастся директория webgrind, которую нужно скопировать в директорию любого сайта и обратиться к ней из браузера. Далее, чтобы в Debian заработало построение графиков в конфигурационном файле config.php нужно поправить путь до исполняемого файла graphviz. Должно получиться так:
static $dotExecutable = '/usr/bin/dot';
Кроме того, можно подправить часовой пояс:
static $defaultTimezone = 'Europe/Moscow';
В заголовке можно выбрать профиль и поставить галочку учитывать ли встроенные функции. В самой таблице видны функции, количество вызовов, время работы самой функции и время с учетом ожидания. Чтобы углубиться в функции достаточно щелкнуть по треугольной стрелочке. В моем случае при достаточно объемных профилях (от нескольких мегабайт), ожидание результата было излишне большим. Вероятно, для достаточно крупных профилей лучше использовать локальные программы просмора.
График может выглядеть следующим образом:
Обратите внимание, что webgrind не стоит использовать на производственных серверах, так как какая-либо авторизация не предусмотрена, но при этом есть доступ к коду файлов на php. В случае необходимости используйте хотя бы базовую авторизацию Apache.
Также существуют программы для анализа профилей как под Linux:
http://kcachegrind.sourceforge.net/cgi-bin/show.cgi
https://code.google.com/p/xdebugtoolkit/
так и под Windows:
http://sourceforge.net/projects/wincachegrind/
О профилировании
Данные профиля могут помочь вам улучшить ваше приложение, то есть достичь определенных целей, к примеру, понизить потребление памяти, уменьшить время генерации страницы и так далее.
Информация в профиле является стартовой точкой в оптимизации: сообщается сколько времени генерируется результат, сколько памяти используется и сколько вызовов функций происходит. С помощью более подробных данных вы можете улучшить эти показатели.
К примеру, если вы используете фреймворк, то использование некоторых функций фреймворка может вести к вызову нескольких базовых функций. Если вы читаете некоторые данные несколько раз, то, возможно, стоит сохранить результат в переменную.
Также профайлер может помочь понять где стоит использовать кэширование PHP-кода, к примеру, с помощью APCu или memcached.
Прежде всего, стоит оптимизировать функции, который требуют больше всего времени на исполнение. После того, как все оптимизировано и кажется, что улучшать больше нечего, стоит отсортировать функции по количеству вызовов и поработать над его понижением. Даже если PHP работает быстро, то стоит подумать, нужно ли вызывать функции так часто?
При обнаружении следующих ситуаций стоит подумать о кэшировании:
- Неизменяемые функции вызываются внутри цикла,
- Некое содержимое генерируется дважды,
- Содержимое, которое не изменяется генерируется каждый раз,
- Содержимое генерируется, даже если не используется.
Не стоит кэшировать все подряд, так как память тоже ценный ресурс. Кэшируйте те данные, к которым обращаетесь постоянно. Также кэширование имеет мало смысла в случае если кэширование тратит больше ресурсов, чем экономит.
Кроме кэширования в коде не стоит забывать о кэшировании с помощью веб-сервера (кэширование в nginx), а также на стороне клиента. Если использовать правильные заголовки, то многие запросы могут быть разрешены еще до поступления на сервер.
Ссылки
http://kurapov.name/rus/technology/web/php/php_profiling/ - об инструментах профилирования на русском,
http://techportal.inviqa.com/2009/12/01/profiling-with-xhprof/ - достаточно подробно о профилировании на английском,
http://pinba.org/ - система мониторинга нагрузки на php-скрипты в реальном времени. Использует MySQL.
Полезные статьи:
Анализ запросов к mysql.
Анализ веб-сервера.
Опубликовано