Профилирование кода позволяет выявить медленные участки в коде, что позволит в случае необходимости устранить их.
Новый PHP профайлер XHprof от компании Facebook — это альтернатива Xdebug (PHP профайлер Xdebug). XHprof был разработан специально для Facebook и начиная с март 2009 года его исходный код стал доступен для скачивания.
Как работает XHprof?
XHProf работает по принципу декомпозиции системы на вызовы функций (методов) и построения статистики в разрезе их ресурсопотребления. В результате получаем информацию: количество выделяемой памяти, количество вызовов функций, время исполнения и т.д.
Установка XHProf
С марта 2009 года XHprof доступен как пакет PECL, поэтому его установка не составит особого труда. Для Windows пакет не доступен.
# pecl search xhprof Retrieving data...0% Matched packages, channel pecl.php.net: ======================================= Package Stable/(Latest) Local xhprof 0.9.2 (beta) XHProf: A Hierarchical Profiler for PHP
Т.к. пакет xhprof находится в стадии beta, то нужно разрешить его установку:
# pecl config-get preferred_state stable # pecl config-set preferred_state beta # pecl config-get preferred_state beta
Если попытаться установить пакет через PECL, то получим ошибку:
# pecl install xhprof downloading xhprof-0.9.2.tar ... Starting to download xhprof-0.9.2.tar (Unknown size) ....................................................................done: 1,506,816 bytes 11 source files, building running: phpize Cannot find config.m4. Make sure that you run '/usr/local/bin/phpize' in the top level source directory of the module ERROR: `phpize' failed
Поэтому выполняем следующие шаги:
# wget http://pecl.php.net/get/xhprof-0.9.2.tgz # tar xvf xhprof-0.9.2.tgz # cd ./xhprof-0.9.2/extension/ # phpize # ./configure --with-php-config=/usr/local/bin/php-config # make # make install Installing shared extensions: /usr/local/lib/php/20060613/ # make test
Удалять папку xhprof-0.9.2 не следует, т.к. там содержатся утилиты GUI для визуального представления информации профайлера.
Подключаем модуль xhprof к PHP — редактируем файл php.ini (добавляем в конец файла):
[xhprof] extension=xhprof.so xhprof.output_dir="/var/tmp/xhprof"
Для папки «/var/tmp/xhprof» должен быть доступ на запись, т.к. туда будут сохраняться результаты профайлинга.
Перезагрузите Apache. При вызове phpinfo() появится информация, что подключен модуль xhprof — значит все работает.
Настройка XHProf UI (GUI)
В пакет XHprof входит очень удобный интерфейс для анализа отчетов профилирования. XHprof позволяет строить отчеты, как в текстовом так и графическом ввиде.
В установочной папке xhprof-0.9.2 Вы найдете папку xhprof_html и xhprof_lib, которые нам понадобятся:
• xhprof_html — доступ к GUI
• xhprof_lib — библиотека для отображения и анализа кода (computing flat profile info, computing diffs, aggregating data from multiple runs, etc.).
Папку xhprof_lib размещаем в /usr/local/share/php/ или /usr/local/lib/php/ в зависимости от ОС. Таким образом будет доступ к библиотеки будет глобальный. В нашем случае получится: /usr/local/share/php/xhprof_lib/. Или как вариант папку xhprof_lib можно положить в наш проект.
В зависимости от того как Вы настроете доступ к GUI xhprof, нужно положить xhprof_html в соответствующее место. К примеру, можно создать субдомен http://xhprof.project/ или положить в корень проекта http://xhprof/.
Небольшой пример использования
В качестве примера взят пример с сайта highload.com.ua:
function user_array_intersect( $a, $b ) { $res = array(); foreach ( $a as $k => $v ) { if ( in_array($v, $b) ) { $res[] = $v; } } return $res; } function execute() { $a = range(rand(100, 300), rand(700, 900)); $b = range(rand(100, 300), rand(700, 900)); $r1 = user_array_intersect($a, $b); $r2 = array_intersect($a, $b); } # Инициализируем профайлер - будем считать и процессорное время и потребление памяти xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); # Выполняем "программу" execute(); # Останавливаем профайлер $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://xhprof/index.php?run=$run_id&source=xhprof_test"; # Хост, который Вы настроили ранее на GUI профайлера echo "\n";
В этом скрипте мы сравним отличие в эффективности работы встроенной функции array_intersect и ее самописного клона user_array_intersect. После описания функций мы подключили профайлер для генерации и сохранения отчета. Посмотрим на отчет:
Из отчета видно, что эффективность собственной реализации функции array_intersect в два раза меньше встроенной (еще одно напоминание об использовании стандартных средств прежде всего!). Небольшая справка по терминологии отчетов:
• Incl[usive] Time — время, потраченное на функцию и на все функции, вызванные из нее
• Excl[usive] Time — время, потраченное на функцию без учета времени на вложенные функции
На скриншоте показана только часть отчета, кроме этих показателей отчет также содержит статистику по процессорным затратам и использованной памяти.
Графические отчеты
XHprof позволяет строить графические отчеты. Для построения он использует внешний инструмент Graphviz, поэтому убедитесь, что он установлен. Графический отчет вышеуказанного скрипта выглядит так:
Графический отчет позволяет визуально оценить ресурсоемкость каждой функции (красный должен привлечь внимание!). Как видим, в примере самой затратной функцией для ресурсов стала in_array(), которая сама по себе не является проблемой но говорит о плохом техническом решении.
Профилирование production проектов
XHprof позволяет профилировать не только отдельные участки кода но и production проекты. Т.к. профилирование проектов в среде production процесс ресурсоемкий, то главный тут критерий — производительность. И XHprof тут прекрасно справляется, т.к. создан он был именно для таких целей. Во-первых XHprof написан на C, во-вторых имеет ряд настроек:
• Таймер CPU на Linux системах имеет большой оверхед, поэтому разработчики рекомендуют использовать профайлер в режиме «elapsed time + memory»:
// elapsed time profiling (default) + memory profiling xhprof_enable(XHPROF_FLAGS_MEMORY);
• Сбор данных профайлера будет весьма точно отражать реальную картину, если его запускать не каждый раз, а случайно и равнораспределенно, например для запуска каждый сотый раз:
if (mt_rand(1, 100) == 1) { xhprof_enable(XHPROF_FLAGS_MEMORY); $xhprof_on = true; } ... if ($xhprof_on) { $xhprof_data = xhprof_disable(); }
• Режим Lightweight Sampling — в этом режиме профилирование выполняется в течении короткого промежутка во времени (сэмплами) — 0.1 секунды
Пример профилирования production проекта
В качестве примера используем проект на Yii — Hello World!
Наш проект http://project/.
GUI нашего профайлера (содержимое папки xhprof_html) http://xhprof/.
xhprof_lib находится в «/usr/local/share/php/xhprof_lib».
Создаем 2 файла (header.php и footer.php).
header.php
<?php if (extension_loaded('xhprof')) { // Способ 1 - файлы лежат в проекте // include_once '/usr/local/share/php/xhprof_lib/utils/xhprof_lib.php'; // include_once '/usr/local/share/php/xhprof_lib/utils/xhprof_runs.php'; // Способ 2 - файлы лежат в /usr/local/share/php/xhprof_lib include_once dirname(__FILE__) . '/xhprof_lib/utils/xhprof_lib.php'; include_once dirname(__FILE__) . '/xhprof_lib/utils/xhprof_runs.php'; xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); }
footer.php
<?php if (extension_loaded('xhprof')) { $profiler_namespace = 'myapp'; // namespace for your application $xhprof_data = xhprof_disable(); $xhprof_runs = new XHProfRuns_Default(); $run_id = $xhprof_runs->save_run($xhprof_data, $profiler_namespace); // url to the XHProf UI libraries (change the host name and path) $profiler_url = sprintf('http://' . $_SERVER['SERVER_NAME'] . '/xhprof/index.php?run=%s&source=%s', $run_id, $profiler_namespace); // Можем сделать защиту по айпи, или добавить $_GET параметр if (in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'))) { // На нашей странице появится ссылка "Profiler output", которая ведет на GUI XHprof с уникальными идентификатором отчета echo '<br/><br/><a href="'. $profiler_url .'" target="_blank">Profiler output</a>'; } }
Для внедрения профайлера в наш проект есть 2 способа:
1) Создаем файл .htaccess
php_value auto_prepend_file ../xhprof/header.php php_value auto_append_file ../xhprof/footer.php
2) Добавляем вызов в файла в наш index.php
<?php include('xhprof/header.php'); // include Yii bootstrap file require_once(dirname(__FILE__).'/framework/yii.php'); // create a Web application instance and run Yii::createWebApplication()->run(); include('xhprof/footer.php');
Загружаем страницу сайта. Внизу страницы появляется ссылка «Profiler output», которая ведет на GUI XHprof с уникальными идентификатором отчета. Каждый раз, когда мы обновляем страницу отчет перегенирируется и идентификатор изменится.
Получаем отчет:
Показатели:
• Total Incl. Wall Time (microsec): 18,710 microsecs (время затраченное на выполнение функций с учетом ожидания ответов от сокетов, файловой системы и других ресурсов )
• Total Incl. CPU (microsecs): 16,309 microsecs (время затраченное на выполнение функций)
• Total Incl. MemUse (bytes): 527,604 bytes (использование памяти)
• Total Incl. PeakMemUse (bytes): 529,428 bytes (пиковое использование памяти)
• Number of Function Calls: 179 (количество вызовов функций)
Что почитать:
• XHProf Documentation
• Pecl: xhprof
• Profiling with XHProf
• XHprof — профилирование PHP от Facebook
• Профилирование PHP-кода
Декабрь 13th, 2009 at 23:11
[…] This post was mentioned on Twitter by Abrdev Blog and Igor Brovchenko, Igor Brovchenko. Igor Brovchenko said: XHprof – профайлер PHP от Facebook http://bit.ly/85G7pJ […]
Декабрь 14th, 2009 at 16:22
Честно признаться, я бы не променял xdebug+KCacheGrind на XHProf.
В xdebug настроек минимум, поставил и работай.
А с XHProf получается такая ситуация: имей мороку с установкой, потом разбирайся как использовать, потом ищи компоненты для отображения отчетов, а в результате отчеты ничем не лучше xdebug+KCacheGrind, и может быть даже хуже. К тому же xdebug существует для всех основных платформ, в отличие от XHProf
Декабрь 15th, 2009 at 16:15
Для меня XHProf ещё один дополнительный инструмент. Xdebug никто не отменял :). С XHProf один раз рабозрался, установил, настроил. Очень удобно, никакие GUI дополнительные не нужны. Кроме KCacheGrind, есть ещё и WinCacheGrind — это если кто под виндой. В любом случае инструмент полезный, за что отдельный респект Facebook.
Декабрь 16th, 2009 at 12:43
Хотя у xdebug тоже есть Web GUI: http://code.google.com/p/webgrind/
Декабрь 17th, 2009 at 23:44
[…] первом посте про XHProf: XHProf – профайлер PHP от Facebook, рассказывалось, что это за инструмент, как его […]
Апрель 16th, 2010 at 13:29
Профилирование продакшена, теме более равнораспределённое — это настоящая находка. Частенько не могу разобраться, куда уходит процессорное время. Спасибо за статью.