Dec 13 2009

XHprof — профайлер PHP от Facebook

Category: PHP,Отладкаingvar @ 17:32

Профилирование кода позволяет выявить медленные участки в коде, что позволит в случае необходимости устранить их.

Новый 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. После описания функций мы подключили профайлер для генерации и сохранения отчета. Посмотрим на отчет:

screenshot-xhprof-hierarchical-profiler-report-mozilla-firefox

Из отчета видно, что эффективность собственной реализации функции array_intersect в два раза меньше встроенной (еще одно напоминание об использовании стандартных средств прежде всего!). Небольшая справка по терминологии отчетов:

Incl[usive] Time — время, потраченное на функцию и на все функции, вызванные из нее
Excl[usive] Time — время, потраченное на функцию без учета времени на вложенные функции

На скриншоте показана только часть отчета, кроме этих показателей отчет также содержит статистику по процессорным затратам и использованной памяти.

Графические отчеты

XHprof позволяет строить графические отчеты. Для построения он использует внешний инструмент Graphviz, поэтому убедитесь, что он установлен. Графический отчет вышеуказанного скрипта выглядит так:

callgraphphp

Графический отчет позволяет визуально оценить ресурсоемкость каждой функции (красный должен привлечь внимание!). Как видим, в примере самой затратной функцией для ресурсов стала 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 с уникальными идентификатором отчета. Каждый раз, когда мы обновляем страницу отчет перегенирируется и идентификатор изменится.

Получаем отчет:

XHProf- Hierarchical Profiler Report_12607101

Показатели:
• 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-кода

Tags: , ,

6 Responses to “XHprof — профайлер PHP от Facebook”

  1. Tweets that mention XHprof – профайлер PHP от Facebook | Блог веб-разработчика -- Topsy.com says:

    […] This post was mentioned on Twitter by Abrdev Blog and Igor Brovchenko, Igor Brovchenko. Igor Brovchenko said: XHprof – профайлер PHP от Facebook http://bit.ly/85G7pJ […]

  2. web-junior says:

    Честно признаться, я бы не променял xdebug+KCacheGrind на XHProf.
    В xdebug настроек минимум, поставил и работай.
    А с XHProf получается такая ситуация: имей мороку с установкой, потом разбирайся как использовать, потом ищи компоненты для отображения отчетов, а в результате отчеты ничем не лучше xdebug+KCacheGrind, и может быть даже хуже. К тому же xdebug существует для всех основных платформ, в отличие от XHProf

  3. ingvar says:

    Для меня XHProf ещё один дополнительный инструмент. Xdebug никто не отменял :). С XHProf один раз рабозрался, установил, настроил. Очень удобно, никакие GUI дополнительные не нужны. Кроме KCacheGrind, есть ещё и WinCacheGrind — это если кто под виндой. В любом случае инструмент полезный, за что отдельный респект Facebook.

  4. ingvar says:

    Хотя у xdebug тоже есть Web GUI: http://code.google.com/p/webgrind/

  5. XHprof: производительность популярных PHP фреймворков | Блог веб-разработчика says:

    […] первом посте про XHProf: XHProf – профайлер PHP от Facebook, рассказывалось, что это за инструмент, как его […]

  6. Павел says:

    Профилирование продакшена, теме более равнораспределённое — это настоящая находка. Частенько не могу разобраться, куда уходит процессорное время. Спасибо за статью.

Leave a Reply