XHProf и xDebug - профилирование (profiling) кода PHP. XHProf и xDebug - профилирование (profiling) кода PHP Быстрый profile php id

С помощью систем для профилирования можно собрать информацию о том, какие функции в 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

После этого в код php-скрипта в месте, откуда должен начаться сбор данных добавляем строку:

Xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);

В скобках указаны параметры для сбора данных. В данном случае будет осуществляться сбор данных по нагрузке на процессор и по использованию оперативной памяти. Возможен еще один параметр XHPROF_FLAGS_NO_BUILTINS при использовании которого данные по встроенным функциям не собираются.

$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 в кавычках указано название профиля, которое можно задать произвольно.

Результат в обработанном виде выглядит следующим образом:

Если указать параметр 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

Также для php profiler xhprof существуют сторонние веб-интерфейсы использующие базы данных:

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:

О профилировании

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

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

К примеру, если вы используете фреймворк, то использование некоторых функций фреймворка может вести к вызову нескольких базовых функций. Если вы читаете некоторые данные несколько раз, то, возможно, стоит сохранить результат в переменную.

Также профайлер может помочь понять где стоит использовать кэширование PHP-кода, к примеру, с помощью APCu или memcached .

Прежде всего, стоит оптимизировать функции, который требуют больше всего времени на исполнение. После того, как все оптимизировано и кажется, что улучшать больше нечего, стоит отсортировать функции по количеству вызовов и поработать над его понижением. Даже если PHP работает быстро, то стоит подумать, нужно ли вызывать функции так часто?

При обнаружении следующих ситуаций стоит подумать о кэшировании:

  • Неизменяемые функции вызываются внутри цикла,
  • Некое содержимое генерируется дважды,
  • Содержимое, которое не изменяется генерируется каждый раз,
  • Содержимое генерируется, даже если не используется.

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

Кроме кэширования в коде не стоит забывать о кэшировании с помощью веб-сервера (), а также на стороне клиента. Если использовать правильные заголовки, то многие запросы могут быть разрешены еще до поступления на сервер.

The profile data loop is the most complex out of all the custom BuddyPress loops. It’s actually two loops in one, the first is to loop through profile field groups, and the second to loop through profile fields in that profile field group.

Standard Loop

This user does not have a profile.

Accepted Parameters

The bp_group_has_profile() function will accept a number of parameters that will manipulate the data being returned.

  • profile_group_id optional

    By default all groups and all fields will be displayed. If you provide the ID of a profile field group, then only the fields in this group will be displayed.

    • Default value: false
  • user_id optional

    The ID of the user you want to fetch the profile data for. This is required if you are outside a member profile URL (/members/andy/…), otherwise it is the ID of the displayed user.

    • Default value: bp_displayed_user_id()
  • member_type optional

    Limit fields by those restricted to a given member type, or array of member types. If $user_id is provided, the value of $member_type will be overridden by the member types of the provided user. The special value of ‘any’ will return only those fields that are unrestricted by member type – i.e., those applicable to any type.

    • Default value: false
  • hide_empty_groups optional

    By default empty groups will not be displayed. If you provide the 0 value, then all the groups will be displayed.

    • Default value: true
  • hide_empty_fields optional

    By default, only show empty fields if we’re on the Dashboard, or we’re on a user’s profile edit page, or this is a registration page. If you provide the 0 value, then all the fields will be displayed on your page.

    • Default value: !is_network_admin() && !is_admin() && !bp_is_user_profile_edit() && !bp_is_register_page()
  • fetch_fields optional

    Whether to fetch each group’s fields.

    • Default value: false
  • fetch_fields_data optional

    Whether to fetch data for each field. Requires a $user_id .

    • Default value: false
  • exclude_groups optional

    Comma-separated list or array of group IDs to exclude.

    • Default value: array()
  • exclude_fields optional

    Comma-separated list or array of field IDs to exclude.

    • Default value: array()
  • update_meta_cache optional

    Whether to pre-fetch xprofilemeta for all retrieved groups, fields, and data.

    • Default value: true

Advanced Usage

Fetch all the profile data for the user with ID 10 .

Fetch the profile data for fields in the profile group ID 2 for the user with ID 10 .

Fetch the profile data for fields in the profile group ID 2 .

Fetch all the profile data, even empty fieds and groups, for current user.

Fetch all the profile data for the user with ID 10 , excluding fields with ID 5, 6, 7 .

Профилирование приложения — это сбор данных о скорости выполнения различных участков программы (файлов и функций). Существует множество инструментов профилирования PHP, но не все инструменты подходят для проведения анализа прямо в продакшне.

XHProf — мега простой профайлер, который собирает статистику прямо во время работы приложения почти без оверхеда .

Зачем профилировать?

Если приложение начинает работать медленно, профилирование поможет узнать, какая именно часть тупит. Результат профилирования — это обычно список выполненных функций и времени их исполнения.

Профилирование стоит делать до любой оптимизации приложения. В противном случае — будете руководствоваться догадками. Скорее всего неправильными.

Проблема Xdebug

Xdebug — мощное решение для PHP. Но сама платформа Xdebug настолько тяжелая, что ее нельзя использовать на работающих сайтах . XDebug создает значительную нагрузку на ресурсы сервера и замедляет приложение.

С другой стороны, проблемы на "живом" сайте могут быть совершенно не такими, как в среде разработчика. Профилирование только на компьютерах разработчиков будет показывать лишь часть проблем.

Именно поэтому и было разработано решение XHprof . Оно предназначено для применения в работающих приложениях. Основная идея этого профайлера — создавать минимум нагрузки на приложение при этом собирать все необходимые данные о скорости работы. Решение разработано ребятами из Facebook и поддерживается новыми версиями PHP .

XHProf

Установка

На Debian XHprof есть в sid пакетах, поэтому: apt-get install xhprof

Вы также можете собрать XHprof самостоятельно.

Включение профилирования

Пусть у нас есть скрипт с таким кодом:

execute();

Проведем профилирование с помощью XHprof. Для этого на этой странице необходимо:

  1. Включить профайлер в самом начале.
  2. В самом конце программы остановить профайлер и сохранить полученные данные.

Это будет выглядеть так:

# Инициализируем профайлер xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); # Выполняем программу после включения профайлера execute(); # Останавливаем профайлер после выполнения программы $xhprof_data = xhprof_disable();

# Сохраняем результат профилирования в переменную $xhprof_data

  • Функция xhprof_enable() принимает в качестве аргументов флаги. XHPROF_FLAGS_CPU для фиксирования статистики процессора, XHPROF_FLAGS_MEMORY — для памяти, XHPROF_FLAGS_NO_BUILTINS — для игнорирования встроенных функций.
  • xhprof_disable() выключит профайлер и вернет собранную статистику.

Отчеты

Генерация

Собранные данные можно проанализировать в интерфейсе XHprof для построения отчетов. Для этого, необходимо скачать исходники XHprof : cd /var/www; wget http://pecl.php.net/get/xhprof-0.9.4.tgz gzip -d xhprof-0.9.4.tgz tar -xvf xhprof-0.9.4.tar

После этого необходимо внести изменения в скрипт:

include_once "/var/www/xhprof-0.9.4/xhprof_lib/utils/xhprof_lib.php"; include_once "/var/www/xhprof-0.9.4/xhprof_lib/utils/xhprof_runs.php"; $xhprof_runs = new XHProfRuns_Default(); $run_id = $xhprof_runs->save_run($xhprof_data, "test");

# Новый код сохраняет отчет для использования в графическом интерфейсе

Интерфейс для отчетов

Чтобы увидеть отчет, необходимо настроить виртуальный хост на папку /var/www/xhprof-0.9.4/xhprof_html. Например, в Nginx:

Server { server_name xh..9.4/xhprof_html; index index.php; location ~* \.(php)$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } } nginx -s reload

После этого появится список отчетов:

Таблица содержит список функций, которые были выполнены в рамках одной страницы с дополнительной информацией:

  • Calls — количество и процентное соотношение вызовов функции.
  • Incl. Wall Time — время выполнения функции с вложенными функциями.
  • Excl. Wall Time — время выполнения функции без вложенных функций.
  • Incl. CPU — процессорное время с вложенными функциями.
  • Excl. CPU — процессорное время без вложенных функций.
  • Incl. MemUse — потребление памяти с вложенными функциями.
  • Excl. MemUse — потребление памяти без вложенных функций.
  • Incl. PeakMemUse — максимальное потребление памяти с вложенными функциями.
  • Excl. PeakMemUse — максимальное потребление памяти без вложенных функций.

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

Чтобы построить графический отчет, убедитесь, что у Вас установлен graphviz: apt-get install graphviz

Ресурсоемкие участки кода выделены желтым (средние) и красным (самые тяжелые). Это те участки кода, которые используют множество ресурсов относительно всей остальной программы. Это может быть одна медленная функция или большое количество вызовов быстрой функции. В нашем примере функция str_replace() помечена красным из-за 262 вызовов.

Агрегатные отчеты

Интерфейс XHprof также позволяет просматривать агрегатную информацию сразу с нескольких отчетов. Для этого run_id передаются через запятую: http://xh..php?run=53a894f6d5d9b,53a894fcf126e &source=test

TL;DR

Используйте XHprof для профилирования PHP прямо в продакшне.