Как измерить скорость расчета доставки в Битрикс

Проблема медленного расчёта доставки в Битрикс

Расчёт стоимости и сроков доставки — один из наиболее ресурсоёмких этапов оформления заказа в Битрикс. Каждая служба доставки делает внешний HTTP-запрос к своему API: СДЭК, Boxberry, Почта России, DHL — все они отвечают с разной скоростью. На странице корзины или оформления заказа Битрикс запрашивает расчёт сразу у всех подключённых служб, и если хотя бы одна из них отвечает медленно или вовсе недоступна, пользователь видит крутящийся прелоадер по несколько секунд.

Чтобы оптимизировать этот процесс, нужно сначала измерить: какая именно служба тормозит и насколько. Без данных профилирования любые попытки ускорить расчёт — это работа вслепую. В этой статье показан простой способ логировать время расчёта каждой службы доставки через стандартный EventManager Битрикса.

Почему важно профилировать службы доставки

Практика показывает, что 80% проблем с медленным расчётом доставки приходится на 1-2 службы из всех подключённых. Часто это:

  • Служба с нестабильным API, которая периодически не отвечает по 10-15 секунд.
  • Устаревший модуль с неоптимальным кодом, делающий несколько запросов вместо одного.
  • Служба, которую магазин перестал использовать, но не отключил — она продолжает тормозить всех остальных.

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

Где разместить код

Код обработчика событий размещается в файле /bitrix/php_interface/init.php. Этот файл подключается Битриксом при каждом запросе раньше любого другого кода сайта, что делает его идеальным местом для глобальных обработчиков событий. Если файл не существует — создайте его, Битрикс автоматически подхватит его при следующем запросе.

Код профилировщика

Добавьте следующий код в init.php. Лог будет записываться в файл /delivery_time_log.txt в корне сайта:

Объяснение кода

EventManager и событие onSaleDeliveryServiceCalculate

EventManager::getInstance()->addEventHandler() — стандартный способ подписаться на событие Битрикса. Первый аргумент — модуль (sale), второй — имя события (onSaleDeliveryServiceCalculate). Это событие вызывается дважды для каждой службы: перед началом расчёта и после его завершения. Именно это позволяет измерить время.

Микросекундный таймер

microtime(true) возвращает текущее время в секундах с микросекундной точностью в виде числа с плавающей точкой. При первом вызове события для конкретной службы (первый вызов) — фиксируем время старта в массиве $timers. При втором вызове — вычисляем разницу и получаем время расчёта в секундах с точностью до четырёх знаков после запятой.

Статические переменные

Массивы $timers и $logged объявлены как static внутри замыкания. Это означает, что они сохраняют своё значение между вызовами одного и того же обработчика в рамках одного HTTP-запроса. Без static каждый вызов события начинал бы с пустыми массивами.

Идентификация службы доставки

$delivery->getId() возвращает ID службы доставки из базы данных. Если по какой-то причине ID недоступен, используется spl_object_hash($shipment) — уникальный хеш объекта, гарантированно отличающийся для разных отправлений.

Debug::writeToFile()

Встроенный метод Битрикса для записи в файл. Принимает массив данных, метку и путь к файлу. Записи добавляются в конец файла, не перезаписывая предыдущие.

Как читать логи

После нескольких оформлений заказа откройте файл /delivery_time_log.txt в корне сайта. Каждая запись содержит дату, название службы доставки и время расчёта в секундах:

Время меньше 1 секунды — норма. Время 2-3 секунды — повод обратить внимание. Время свыше 5 секунд — критическая проблема, требующая немедленного решения.

Что делать, если нашли медленную службу

  • Временно отключите службу в настройках магазина (Магазин → Настройки → Службы доставки) и проверьте, ускорился ли расчёт.
  • Обновите модуль службы доставки — разработчики часто выпускают исправления производительности.
  • Проверьте доступность API службы с вашего сервера: curl -w "%{time_total}" https://api.cdek.ru/.
  • Настройте таймаут в коде модуля — большинство служб позволяют задать максимальное время ожидания ответа от API.
  • Переведите расчёт в асинхронный режим — Битрикс поддерживает AJAX-расчёт доставки, при котором страница загружается немедленно, а доставка пересчитывается в фоне.

Альтернативные инструменты профилирования в Битрикс

Помимо описанного метода, для профилирования производительности в Битрикс доступны следующие инструменты:

  • Панель отладки Битрикс — включается через параметр BX_DEBUG в dbconn.php, показывает время выполнения запросов и событий прямо на странице.
  • BitrixMainDiagDebug::startTimeLabel() / endTimeLabel() — встроенные методы для замера времени отдельных участков кода с выводом в стандартный лог Битрикса.
  • XHProf / Tideways — профилировщики PHP-уровня, дающие полную картину вызовов функций с временем выполнения каждой.

Итог

Описанный обработчик события — минимальный и ненавязчивый инструмент профилирования. Он не влияет на производительность самого расчёта и не изменяет логику работы магазина. Добавьте его на несколько дней, соберите статистику, найдите проблемную службу и устраните причину — после этого код можно удалить из init.php.