Профайлинг Laravel приложений с XDebug и PHPStorm

Привет, меня зовут Ваня, я работаю PHP-разработчиком в Санкт-Петербургском электротехническом университете ЛЭТИ. Профайлинг приложений важный этап перед релизом ресурсоёмкой фичи, везде трубят про удобную отладку PHP-приложений при помощи XDebug и PHPStorm, однако напрочь забывают про замеры времени операций, которые, порой, превышают те самые 3 секунды, которые пользователь будет ждать на странице. Если у Вас есть метод API, который долго работает, самое время его проверить профайлером XDebug, а PHPStorm поможет красиво визуализировать и изучить файл профиля.

Я не буду писать про настройку XDebug вместе с Docker контейнером и Laravel Sail, потому что про это есть тонна статей, в том числе и на русском. Однако, эта статья предполагает, что у Вас есть настроенный XDebug в связке с PHPStorm в Docker контейнере или другой среде.

Заводим профайлер в XDebug

В минимальной настройке нам необходимо дополнить список включенных режимов режимом profile. Если Вы используете Laravel Sail, то можно изменить переменную среды SAIL_XDEBUG_MODE в файле .env, или напрямую изменить режимы в конфигурационном файле PHP. Режимы указываются параметром xdebug.mode через запятую. Пример: xdebug.mode=develop,debug,profile.

По умолчанию файл профайлинга сохраняется в директорию /tmp, чтобы нам было удобнее давайте изменим директорию сохранения на /var/www/html (для Laravel Sail эта директория монтируется к директории проекта), за это отвечает конфигурация xdebug.output_dir=/var/www/html.

Рекомендую добавить в .gitignore все выходные файлы: /cachegrind.out*.

Давайте теперь проверим нашу настройку, которая по итогу выглядит как-то так:

[XDebug]
xdebug.mode = develop,debug,profile
xdebug.start_with_request = yes
xdebug.discover_client_host = true
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
xdebug.idekey = PHPSTORM
xdebug.output_dir = /var/www/html

Просмотр профайла в PHPStorm

Перейдите на страницу в браузере, которую хотите изучить профайлером. После полной загрузки в корне проекта у нас создался файл cachegrind.out.<какое-то число>.gz, давайте изучим его через инструмент для просмотра в PHPStorm. Честно говоря не знаю, где он находится в меню, поэтому воспользуемся сочетанием клавиш для вызова окна поиска действий Ctrl+Shift+A. Ищем «XDebug Profiler» и заходим в него.

Диалоговое окно поиска действий

Диалоговое окно поиска действий

Можете нажать Ctrl+2 чтобы сразу перейти в директорию проекта. Выбираем наш cachegrind.out.<какое-то число>.gz и видим что профайла необходимого метода нет, только server.php.

Наш server.php и больше ничего

Наш server.php и больше ничего

На этом моменте я немного расстроился, подумал, что с Laravel профайлер XDebug нормально не работает. Какое-то время пришлось изучать проблему, на StackOverflow была такая же проблема, однако к ней не было ни единого ответа. Через какое-то время я понял, что дело в файле и настройках XDebug.

Немного изменяем конфигурацию профайлера

И так, чтобы всё работало как нам необходимо, нужно понять в чём же проблема. Если изучить логи команды php artisan serve, то мы увидим два запроса:

2024-01-23 22:44:56 ................................................... ~ 0s
2024-01-23 22:44:56 /favicon.ico ...................................... ~ 0s

Здесь и кроется ответ. Дело в том, что artisan команда serve запускает сервер PHP для разработки в одном потоке, а цифра в файле cachegrind.out означает идентификатор процесса (PID). Так как все запросы идут через один процесс — в файл постоянно перезаписывается результат профайлинга последнего запроса. Решение простейшее: нужно изменить имя выходного файла при помощи конфигурации xdebug.profiler_output_name. Я установил значение cachegrind.out.%R, где %R — это переменная $_SERVER['REQUEST_URI'] (адрес запроса). Другие параметры можно посмотреть в документации XDebug: https://xdebug.org/docs/all_settings#trace_output_name

После перезапуска контейнера видим два файла: один с нашим адресом, а другой со злосчастным favicon_ico.

Наш профайл нужного адреса и favicon.ico

Наш профайл нужного адреса и favicon.ico

Если мы изучим профайл нашего запроса, то увидим всё то, что нам нужно.

Профайл нормального запроса

Профайл нормального запроса

Если Вы исследуете ресурсоёмкие методы, то PHPStorm понадобится какое-то время распарсить профайл, прогресс можно наблюдать в статусбаре.

Это моя первая публикация на Хабре. Если есть вопросы/предложения/критика, пишите в комментариях — обсудим. Телеграм каналы по программированию я не веду, поэтому ссылки не будет. Спасибо за внимание!

© Habrahabr.ru