Сайт на 1С-Битрикс тормозит? Найти проблему помогает Xdebug

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

Нужно срочно найти проблемное место — страдает бизнес.

Что мы имеем:

  • сайт на 1С-Битрикс (проверка сайта проходит без проблем, настройки битрикса в панели производительности — оптимальны);

  • без композита, но с каким-то хитрым кастомным кешем;

  • торговый каталог с ~10 тысячами товаров и множеством различных ценовых политик;

  • несколько нестандартных классов, расположенных в разных папках и вызываемых из разных мест.

Сайт программировали неизвестные нам герои, и потому проблема может быть в любом месте. Начинаем искать.

Что показывает стандартная отладка в 1C-Битриксе?

image00.png

Это статистика некешированной страницы. С кешем – на 5 секунд и на 200 запросов меньше.

В подробной статистике эти 5 секунд уходят на catalog.section. Но на что именно – не понятно. Статистика даёт информацию о скорости и количестве запросов к БД, но не о php-коде, который исполняется почти 8 секунд. Если кликнуть на "время создания страницы", открывается дерево компонентов (тех, что обводятся красной рамочкой на самой странице). Всё, что не входит в компонент, скрывается за названием PHP-код. Где этот код и что делает – непонятно.

Возникают вопросы:

  • Откуда берутся ещё 3 секунды при загрузке страницы из кеша?

  • Откуда эти полторы тысячи некешируемых запросов?

  • Можно ли оптимизировать каталог, чтобы его загрузка занимала меньше времени?

Стандартные средства 1С-Битрикс не дают ответа. 

Помогают инструменты xdebug и модуль bitrix.xdebug. Первое – расширение для php, второе – модуль для Битрикса, работает на основе xdebug.

Кроме отладчика в xdebug есть профилировщик, который собирает информацию о времени выполнения php-функций и записывает эту информацию в трейс (специальный файл). Трейс хранит информацию о времени старта функций, но не времени выполнения.  Для создания и анализа трейса воспользуемся модулем Bitrix.xDebug.

Что для этого нужно:

  1. Поставить Bitrix.xDebug из маркетплейса (бесплатный, в списке модулей будет называться Отладчик).

  2. Включить xdebug (нужно учитывать, что xdebug сильно грузит сервер, поэтому если сервер и “никуда не спешит” – лучше выключить xdebug сразу после снятия трейса).

  3. Запустить создание трейса . Запуск можно сделать или в настройках модуля Отладчика (время лучше ставить хотя бы минут 5, потому что создание трейса значительно замедляет скорость загрузки страницы; путь нужно указывать абсолютный; в Параметрах xdebug руководствуйтесь следующей мыслью: “Чем больше информации вы будете собирать – тем больше времени и места будет занимать трейс”).

image01.png

Без использования модуля битрикса – через xdebug_start_trace(); и xdebug_stop_trace(); в коде, если известно, в каком именно месте тормозит сайт. Но не забудьте в этом случае прописать правильные настройки для xdebug’а в .htaccess ( документация и флаги ).

4. Запустить профилировщик в Bitrix.xDebug для анализа трейса. Полный трейс может весить один-два гигабайта, при анализе он сжимается в несколько раз и записывается в базу. Поэтому если есть вероятность, что сайт из-за этого повиснет – можно скачать трейс и загрузить на локальный или тестовый сервер с уже установленным Bitrix.xDebug и запустить профилирование там.

image02.png

5. В итоге работы появится табличка. Интегральное время – время работы самой функции плюс время работы всех функций внутри неё. Собственное – «чистое» время функции. Интегральное время может показывать некорректный результат, если функция вызывается рекурсивно – тогда получается сумма арифметической прогрессии.

image03.png

Всё замечательно. Но вопрос – а что дальше-то делать?

Выбранный подход: начинаем сверху и идём «вглубь». То есть – выводим полный список функций и поиском по странице ищем, что же у нас вызывается непосредственно с index.php. Скорее всего, это будет или подключение компонента, или require/include. Выбираем самую долгую функцию. Нажимаем на название – видим, что она вызывала. Снова поиск по странице – на этого раз по названию компонента или файла, который подключала эта функция. И так через пару итераций доходим до наиболее «подозрительных» функций – интегральное время которых необоснованно велико и вызовы слишком частые. В первую очередь стоит обратить внимание на нестандартные функции, не входящие в ядро Битрикса.

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

На сайте из примера было выявлено несколько слабых мест. 

Первое, которое сразу бросалось в глаза в трейсе — это функция создания меню каталога. 

В шаблоне она вызывалась только один раз, поэтому без трейса на неё бы навряд ли стали смотреть. Оказалось, что это рекурсивная функция , с количеством итераций по количеству элементов, да ещё и на каждой итерации был GetList() с фильтром по единственному id и вызов ещё одной рекурсивной функции для построения ссылки для ЧПУ, в которой тоже был GetList(). Так что в сумме она давала несколько сотен запросов к базе данных. Заменилось за полчаса на стандартный компонент, после чего при кешировании страница стала грузится за полсекунды, с 50 запросами против тысячи раньше.

Второе — остался вопрос со скоростью загрузки страницы без кеша. Путём поиска по странице со списком функций в трейсе обнаружилось, что в шаблоне компонента списка товаров почему-то несколько раз подключается одни и тот же файлы (раз по 20 каждый), плюс ещё слишком большое количество GetList(), которые, как оказалось, вызывались в цикле по элементам (хотя их вполне можно было заменить одним). Вынесение загрузки файлов в одно место помогло снять значительную нагрузку с сервера.

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

Комментарии (2)

...
  • Волочнев Александр
  • 06.05.2015 02:44:58
Рекомендую посмотреть в направлении XHprof, а лучше - сразу Sensiolabs Blackfire. XDebug для данной задачи использовать можно, но неудобно. ОЧЕНЬ неудобно.
...
  • Антон Долганин
  • 14.08.2015 13:38:17
Подход тоже помог посмотреть на проблему, которая лежала на поверхности - на сайте было 550+ инфоблоков, тормозил PHP.
В итоге подход подсказал - ну тормозит потому что их 550+ будем думать с ТП Битрикс и клиентом.

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