| name | bitrix-performance |
| description | Эксперт по производительности и highload 1С-Битрикс (сайты/интернет-магазины на больших объёмах: сотни тысяч товаров, высокий трафик). Используй всякий раз, когда сайт на Битрикс тормозит/зависает/растёт нагрузка; когда проектируешь производительный код (кэш, запросы, каталог на объёмах); когда разбираешь «почему медленно» (Монитор производительности, лог медленных страниц, EXPLAIN, xhprof); когда настраиваешь кэш-слои (компонентный, тегированный, композит, Redis), оптимизируешь CIBlockElement::GetList / D7 ORM, ловишь N+1, работаешь с фасетным индексом умного фильтра, тюнингуешь MySQL/OPcache/PHP-FPM, масштабируешь (веб-кластер). Срабатывай даже без слов «производительность», если речь о том, почему медленно/не масштабируется. Железное правило: источник истины — ИЗМЕРЕНИЕ (perfmon, счётчики, план запроса, slow log), а НЕ память модели; сначала сними замер — потом вывод. Написание кода — скилл bitrix-dev; анализ задачи — bitrix-analyst.
|
Производительность 1С-Битрикс — сначала замер, потом вывод
Аналог 1c-expert, но для Битрикс. Не оптимизируй вслепую. Порядок: снять данные → локализовать → починить → перезамерить.
Глубокие материалы по разделам — references/.
Правило №0: источник истины — измерение
Сначала: панель отладки (для админа) → Монитор производительности (замер под нагрузкой) → лог медленных страниц →
EXPLAIN тяжёлых SQL / xhprof. Только потом — гипотеза и фикс. Непроверенное помечай [проверить].
Быстрый чек-лист «Битрикс тормозит» (по порядку)
- Панель отладки внизу страницы: время генерации, память, число SQL-запросов, число компонентов.
Сотни запросов → N+1 или отключённый кэш.
- Монитор производительности → замер под нагрузкой → топ нагруженных страниц + APDEX. Начинай с топа.
- Лог медленных страниц → худшие URL.
- Кэш: у медленной страницы включён кэш компонента?
CACHE_TYPE=N/CACHE_TIME=0? Автокэширование выключено глобально?
- SQL: slow query log +
EXPLAIN → нет индекса / full scan / тяжёлый JOIN фасета.
- xhprof на проде в пик → что ест время (PHP vs SQL vs внешний API).
- Инфраструктура: OPcache вкл.? Кэш в Redis/memcached, не файлы?
innodb_buffer_pool_size адекватен?
«Проверка системы» Битрикс — всё зелёное?
Локализация:
- «Одна страница медленно» → панель отладки: много SQL → N+1/кэш; мало SQL но долго → PHP (xhprof) или один тяжёлый SQL (EXPLAIN).
- «Весь сайт под нагрузкой» → инфра: OPcache, хранилище кэша,
innodb_buffer_pool, PHP-FPM max_children, CPU/IO.
- «После релиза» → холодный кэш (норма первые минуты) либо новый код в init.php/обработчике. Сравни perfmon до/после.
- «Фильтр/каталог» → фасетный индекс, объём
b_iblock_element_property, число свойств/типов цен.
Кэш — первое оружие (разница 10-100× по времени генерации)
- Компоненты:
$this->startResultCache() → setResultCacheKeys([...]) (только нужные шаблону ключи) →
includeComponentTemplate(). CACHE_TIME, CACHE_TYPE (A/Y/N), CACHE_GROUPS (Y — если контент зависит от прав).
- D7 произвольные данные:
Bitrix\Main\Data\Cache::createInstance() → initCache/startDataCache/endDataCache.
- Тегированный кэш:
Application::getInstance()->getTaggedCache() + registerTag('iblock_id_17') — автосброс при
изменении инфоблока. Требует включённого управляемого кэша. HL-блоки тег НЕ сбрасывают — чисти вручную из обработчика.
- Композит (Composite): мгновенная статика + AJEX-догрузка персонального. Только GET; персональные блоки ОБЯЗАТЕЛЬНО
оборачивать (иначе утечка цен/имён/корзины в общий кэш). Ломается от
RestartBuffer()/незакрытого вывода/ошибок PHP.
- Хранилище кэша — на нагрузке переключить с файлов на Redis (стабильнее memcached, кластер) в
.settings.php.
- Не кэшировать общим кэшем: корзину, авторизацию, персональные цены/скидки — только композит-динамика или AJAX.
Детали, код и подводные камни — references/caching.md.
Запросы и данные
CIBlockElement::GetList: явный select (только нужные поля; не тащить все PROPERTY_*), filter по индексам
(IBLOCK_ID,ACTIVE,SECTION_ID,ID), свойства грузить пакетно, счётчик — SetRowCount/отдельный лёгкий запрос.
- D7 ORM:
*Table::getList(['select','filter','order','limit','count_total'=>true,'cache'=>['ttl'=>3600,'cache_joins'=>true]]);
join через точку; агрегаты — ExpressionField + registerRuntimeField.
- N+1 (запрос в цикле) — главный анти-паттерн: собери ID → один запрос
IN(...); свойства/разделы предзагружай пакетно.
- Прямой
$DB->Query — только для тяжёлых агрегатов/batch; экранируй $DB->ForSql()/каст (иначе SQL-инъекция);
теряешь тегированный сброс.
Детали и примеры — references/queries-and-orm.md.
Объёмы (интернет-магазин)
- Инфоблоки 2.0 (свойства-колонки вместо EAV) при 50K+ товаров; после миграции — вручную создавать индексы MySQL
на связующие колонки.
- Фасетный индекс умного фильтра ускоряет фильтрацию, но деградирует > 10 млн записей фасета (тяжёлые JOIN); каждый
тип цены и множественное свойство SKU удваивают нагрузку.
- Highload-блоки для больших справочников/характеристик (без оверхеда
b_iblock_element_property).
- 1М+ SKU → свойства в HL + инфоблоки 2.0; поиск/фильтр выносить в ElasticSearch/OpenSearch/Meilisearch.
Детали, формулы объёма, тайминги — references/large-catalogs.md.
Инфраструктура
- OPcache обязателен (
max_accelerated_files 100000+, validate_timestamps=0 на проде с деплой-инвалидацией).
- Redis/memcached как хранилище кэша (
.settings.php секция cache).
- MySQL/MariaDB:
innodb_buffer_pool_size 70-80% RAM (главный), transaction-isolation=READ-COMMITTED (требование Битрикс),
innodb_flush_log_at_trx_commit=2, innodb_log_file_size 256-512M. Валидируй «Панелью проверки системы».
- PHP-FPM:
pm.max_children по памяти, pm.max_requests против утечек.
- Веб-кластер (highload): репликация master-slave, общий Redis-пул, синхронизация сессий/файлов, балансировка.
Детали — references/infrastructure.md.
Диагностические инструменты
- Монитор производительности (perfmon): тест конфигурации + замер под нагрузкой (топ страниц, APDEX, SQL vs PHP).
- Панель отладки +
\Bitrix\Main\Diag\Debug::writeToFile() для замера участков.
- xhprof + XHGui (прод в пик), Blackfire/Tideways (APM), slow query log +
EXPLAIN.
- Отладка в
dbconn.php ($DBDebug) / .settings.php (exception_handling.debug — на проде false).
Детали — references/diagnostics.md.
Качество = производительность: статически ловим анти-паттерны (ДО прода)
Проактивный слой (ast-grep / PHPStan-правила toolkit, см. core/linters/ (в репозитории toolkit)):
- Запрос в цикле (
GetList/getList/$DB->Query/GetProperty внутри while/for/foreach) → N+1.
- GetList без явного select на списках → выбор всех полей.
- Компонент с
CACHE_TYPE=>'N' в IncludeComponent(...) → кэш отключён, требует ревью.
SELECT * и конкатенация переменной в $DB->Query.
- Тяжёлые вызовы в init.php/dbconn.php (
GetList/HTTP/file_get_contents(http...)) — на каждом хите.
Это прямой аналог того, как 1c-скилл ловит «запрос в цикле» в BSL. Правила — в core/linters/ast-grep/ (в репозитории toolkit).
Шпаргалка
- Всегда сначала замер. 2. Кэш (компонент → тег iblock_id_* → композит → Redis). 3. Запросы: явный select, индексы,
никаких N+1, ORM с cache. 4. Объёмы: инфоблоки 2.0 + индексы при 50K+, фасет деградирует >10 млн, 1М+ → Elastic+HL.
- Инфра: OPcache, Redis, buffer_pool 70-80%, проверка системы зелёная. 6. Анти-паттерны ловить статически.