Работая с различными PHP проектами часто приходится дебажить приложение чтобы найти и исправить ошибку. Во многих случаях вполне хватает xDebug, однако он не подходит для всех задач. Иногда нужно понять почему та или иная страница долго загружается, что съедает так много памяти или просто как работает большой и запутанный код.
php-spx logo webmageic

В практике приходилось попробовать профилирование с помощью xDebug с дальнейшим построением Flame Graphs но поскольку дамп генерируется долго, а сам граф нужно сделать отдельно, то такой подход не прижился.

Визуализация в QCacheGrind справлялась лучше, но не всегда давала понять что не так.

xHprof был достаточно быстрым но имел тот же недостаток с удобством визуализацией данных.

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

В последнее время я много работаю с Magento 2, но несмотря на довольно хорошую документацию, в реальности мы сталкиваемся реальными челенджами.

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

Поэтому как то в поисках хорошего визуализатора трейсов в виде таймлайнов для PHP я наткнулся на репозиторий PHP-SPX (Simple Profiling eXtension)

Первое на что я обратил внимание, это превью-анимация с таймлайном, флейм графом и списком вызова функций:

image

Мне показалось что это именно то что нужно, все необходимое, да еще и в одном месте. Больше всего меня заинтересовал таймлайн, т.к. он ну очень похож на тот который предлагает Blackfire и Tideways.

При кратком просмотре документации, я решил попробовать установить профайлер.
Доки нам говорят что достаточно скачать исходники и собрать все с помощью phpize и make, а далее подключить в php.ini

git clone https://github.com/NoiseByNorthwest/php-spx.git
cd php-spx
phpize
./configure
make
sudo make install

В случае с докером все так же, только можно переместить исходники в более удобное место. В моем случае это было так:

RUN cd /usr/lib && git clone https://github.com/NoiseByNorthwest/php-spx.git
RUN cd /usr/lib/php-spx && phpize && ./configure && make && make install

Добавляем расширение в конфиг php.ini, тут можем подстроить некоторые параметры:

extension = /usr/lib/php-spx/modules/spx.so
spx.http_enabled = 1
spx.http_key = "dev" #ключ доступа к панели и триггер
spx.http_ip_whitelist = "*" #список IP через запятую с которых разрешено профилирование
spx.data_dir = /var/www/html/spx_dumps #место сохранение дампов, по умолчанию - /tmp/spx

Поскольку профилирование разрешено со всех IP, то просто переходим по такому URL в php проекте.

http://localhost/?SPX_KEY=dev&SPX_UI_URI=/ 


Если все работает правильно то расширение перехватит запрос к приложению и подменит ответ своей панелью управления.

image

Далее отмечаем чекбокс Enabled и открываем любой URL приложения в новой вкладке (например главную страницу).

Профилировать можно и с помощью curl, достаточно добавить соответствующие куки.

curl --cookie "SPX_ENABLED=1; SPX_KEY=dev" http://localhost/

Подобным способом можно дебажить и консольные команды:

SPX_ENABLED=1 SPX_REPORT=full ./bin/console

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

php-spx dumps list

Открываем дамп, ждем конца загрузки:



Видим визуализацию всех вызовов PHP функций и методов в трех вариантах.

Timeline, Flat profile и Flame Graph.

php-spx webmageic

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



Либо изменения цветов по паттерну регулярного выражения во вкладке category



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

На примере профиля из Magento 2 могу сказать что на огромном таймлайне можем увидеть много интересных вещей которые происходят внутри.



Часто можно увидеть такой паттерн-пилу, обычно это означает загрузку данных либо другие операции в цикле. В данном примере это проблема N+1 загрузки URL категорий.



Либо другой пример, когда после выполнения SQL запроса приложение создает PHP объекты.



Если включить добавление внутренних функций PHP в дампы, то увидим их на зуме до микро и наносекунд. Однако такой низкий уровень скорее полезный только для лучшего анализа колл стека чем поиска проблем с производительностью, с исключением возможных curl на внешние API, чтения больших файлов либо других специфических случаев. Обычно обертки фреймворка вполне достаточно для понимания происходящего.



Я использую PHP-SPX в паре с xDebug, это улучшает поиск подходящих мест для брейкпоинтов, а визуализация позволят лучше понять флов выполнения, что очень ускоряет знакомство с ранее неизвестными частями приложения.

Еще несколько примечаний от главного разработчика PHP-SPX:

  • автор не считает что расширение готово к использованию в продакшене, поэтому лучше устанавливать его только локально и на тестовые сервера
  • единственное ограничение доступа к профилированию через веб-интерфейс — это белый список IP и параметр SPX_KEY

Итоги


Из своего опыта использования, могу сказать, что на данный момент PHP-SPX это самый удобный Open-Source профайлер-трейсер для PHP с хорошей визуализацией. Много раз выполнял роль чит-кода позволяющего быстрее разобраться с новым кодом, найти и исправить различные проблемы производительности (особенно в Magento 2), а так же самому писать более надежный и эффективный код.

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

Однако в случае с таймлайном более подробным есть PHP-SPX т.к. он записывает все вызовы (по умолчанию семплинг не используется) в то время как Blackfire ограничивает нас до 1% времени выполнения:
The Timeline Threshold is not an absolute value. It is relative to the way your application performs. The threshold value is calculated by Blackfire as 1% of the duration of the profiled page/script
источник

Может быть кто-то из читателей поделиться в комментариях своим опытом использования PHP-SPX либо других инструментов при разработке PHP приложений?
Демо PHP-SPX можно посмотреть тут
Более подробную информацию о всех настройках и возможностях можно найти в репозитории.