Профілювання PHP-коду для 1С-Бітрікс (Xdebug, Blackfire)
Сторінка завантажується 4 секунди. Nginx відповідає швидко, MySQL теж у порядку — а PHP тратить три секунди незрозуміло на що. Без профайлера це угадування. З профайлером — конкретна функція, конкретний рядок, конкретний час. Розберемо два інструменти, які реально використовуються в проектах на Бітрікс.
Xdebug: профілювання через cachegrind
Xdebug — розширення PHP, яке вміє записувати трасування виконання скрипту у форматі cachegrind. Файл відкривається в KCachegrind (Linux) або QCacheGrind (Windows/Mac).
Встановлення (PHP 8.x):
pecl install xdebug
# або через apt: apt-get install php8.2-xdebug
Конфігурація в php.ini або 99-xdebug.ini:
[xdebug]
zend_extension=xdebug.so
xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=callgrind.out.%p.%r
xdebug.start_with_request=trigger
xdebug.start_with_request=trigger — профілювання запускається тільки при наявності GET-параметра ?XDEBUG_PROFILE=1 або куки. Це важливо: не включайте always на боєвому сервері — генерація cachegrind убиває продуктивність.
Запит з профілюванням:
curl "https://site.ru/catalog/product/?XDEBUG_PROFILE=1" -o /dev/null
У /tmp/xdebug появиться файл callgrind.out.12345.xyz. Відкриваєте в KCachegrind — видите дерево викликів, відсоток часу кожної функції.
Що шукати в профілі Бітрікс
Типові вузькі місця, які вилізають в cachegrind:
-
CIBlockElement::GetList()— викликається десятки разів на одній сторінці без кеша. Шукайте в профілі сумарний часGetList— якщо більше 30% від PHP-часу, проблема в кешуванні компонентів. -
CSQLWhere::GetQuery()— складні фільтри інфоблоку без індексів. -
CBitrixComponent::includeComponent()— якщо вкладено 20+ компонентів, кожен підключає шаблони і CSS, накопичується overhead. -
CUser::IsAuthorized()— на деяких конфігураціях викликається при кожному зверненню до API, не кешується між викликами в одному запиті. -
\Bitrix\Main\ORM\Query\Query::exec()— D7-запити зfetchAll()на великих вибірках без ліміту.
Blackfire: профілювання з агрегацією
Blackfire — SaaS-рішення. Агент встановлюється на сервері, PHP-розширення (blackfire.so) перехоплює виконання, дані йдуть на blackfire.io, результат — інтерактивний граф викликів у браузері.
Встановлення агента та розширення:
# Агент
wget -O - https://packages.blackfire.io/gpg.key | apt-key add -
echo "deb http://packages.blackfire.io/debian any main" > /etc/apt/sources.list.d/blackfire.list
apt-get update && apt-get install blackfire
# PHP-розширення
apt-get install blackfire-php
# Або через PECL:
pecl install blackfire
У php.ini:
extension=blackfire.so
blackfire.agent_socket=tcp://127.0.0.1:8307
Авторизація агента:
blackfire agent:config --server-id=XXXX --server-token=YYYY
blackfire agent:start
Запуск профілювання через CLI:
blackfire run php artisan bitrix:some-command
# або через curl:
blackfire curl https://site.ru/catalog/
Через браузерне розширення Blackfire (Chrome/Firefox) — кнопка Profile прямо на сторінці.
Blackfire vs Xdebug: коли що використовувати
| Критерій | Xdebug cachegrind | Blackfire |
|---|---|---|
| Накладні видатки при профілюванні | Високі (~10–20x уповільнення) | Низькі (~2x) |
| Зручність аналізу | KCachegrind (десктоп) | Веб-інтерфейс, граф |
| Порівняння профілів | Вручну | Вбудована функція diff |
| Профілювання CLI-скриптів | Так | Так |
| Робота з production | Не рекомендується | Можливо (з обережністю) |
| Вартість | Безкоштовно | Freemium |
Xdebug — на dev-сервері для глибокої діагностики. Blackfire — коли потрібно порівняти «до і після» оптимізації або профілювати staging.
Практичний алгоритм оптимізації
- Базовий замір. Беремо сторінку, запускаємо профайлер, фіксуємо топ-5 функцій за часом.
-
Аналіз кореня. Для кожної «дорогої» функції дивимось call stack — хто її викликає і скільки разів. Часто
GetListдорог не сам по собі, а тому що викликається 40 разів підряд. -
Кешування. Включаємо кеш на компоненті (
CACHE_TYPE=A,CACHE_TIME=3600). Або кешуємо результатGetListвручну через\Bitrix\Main\Data\Cache. - Повторний замір. Профілюємо ще раз, порівнюємо з baseline.
-
Оптимізація запитів. Якщо запит повільний — додаємо потрібні поля в
$select, видаляємо зайвіIBLOCK_SECTION_IDбез індексу, переписуємо зGetListна D7 ORM.
Профілювання агентів та CLI
Для фонових агентів (\Bitrix\Main\Diag\ExceptionHandler), кронових скриптів та CLI-команд Xdebug запускається через змінну окруження:
XDEBUG_MODE=profile XDEBUG_OUTPUT_DIR=/tmp/xdebug php -d xdebug.start_with_request=yes /path/to/bitrix-script.php
Blackfire через CLI:
blackfire run php /path/to/bitrix-script.php
Терміни
| Завдання | Тривалість |
|---|---|
| Налаштування Xdebug на dev-сервері | 2–4 години |
| Налаштування Blackfire (агент + розширення) | 4–6 годин |
| Профілювання однієї сторінки + звіт | 2–4 години |
| Профілювання + оптимізація 3–5 вузьких місць | 2–5 днів |
Профілювання без подальшої оптимізації — безсенсовно. Ми не просто знімаємо профіль і здаємо звіт — ми виправляємо знайдені проблеми і замеряємо результат.







