Настройка OPcache и PHP-FPM для 1С-Битрикс: +50% производительности без изменений кода

Правильная настройка OPcache и PHP-FPM даёт заметный прирост производительности Битрикс без изменений бизнес-логики: меньше компиляций PHP на каждый запрос, стабильнее пул воркеров, меньше латентности на «холодных» хитах после рестарта. Ниже — рабочие параметры для продакшна, мониторинг hit rate, realpath cache, preload и типичные ловушки после деплоя.

Расширенный разбор пулов и preload: PHP-FPM: пулы, OPcache и preload. Деплой-чеклист Битрикс: деплой на продакшн.

Настройка OPcache

Откройте ini для той же SAPI, что обслуживает сайт (FPM, не CLI): например /etc/php/8.1/fpm/conf.d/10-opcache.ini.

[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=100000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
; В продакшне — не проверять mtime файлов на каждый запрос:
opcache.validate_timestamps=0
opcache.save_comments=1

max_accelerated_files для Битрикс лучше ставить с запасом: ядро + модули + local легко превышают 10–20 тысяч файлов. Если в статусе видите cache_full — увеличьте memory и лимит файлов.

Важно: при validate_timestamps=0 после каждого деплоя PHP-кода сбрасывайте OPcache, иначе прод будет отдавать старые классы:

# вариант 1: reload пула
systemctl reload php8.1-fpm

# вариант 2: скрипт под веб-пользователем
php -r 'if (function_exists("opcache_reset")) { var_export(opcache_reset()); }'

Сброс из CLI не всегда чистит OPcache FPM (разная SAPI). Надёжнее reload php-fpm или вызов opcache_reset() именно из веб-контекста / отдельного FPM-скрипта за basic-auth.

Настройка PHP-FPM под нагрузку

[www]
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
request_terminate_timeout = 60s

Формула для pm.max_children: доступная RAM для PHP / средний RSS процесса. Оценить размер:

ps aux | grep php-fpm | awk '{print $6}' | sort -n | tail -10

Если выставить 80 children на 4 GB RAM при RSS ~80 MB — получите своп и «сайт лёг». Лучше меньше воркеров и очередь, чем OOM.

pm.max_requests перезапускает воркер после N запросов и снижает утечки памяти в долгоживущих процессах — для Битрикс значение 300–1000 обычно достаточно.

Мониторинг OPcache

$status = opcache_get_status(false);
$mem = $status['memory_usage'];
$stat = $status['opcache_statistics'];
echo round($mem['used_memory'] / 1048576, 1) . " MB used\n";
echo round($stat['opcache_hit_rate'], 2) . "% hit rate\n";
echo 'cached_scripts=' . $stat['num_cached_scripts'] . "\n";
echo 'cache_full=' . (!empty($mem['cache_full']) ? 'yes' : 'no') . "\n";

Ориентир для прогретого продакшна — hit rate выше 98%. Если hit rate низкий при включённом OPcache, чаще всего: маленький memory_consumption, низкий max_accelerated_files, или validate_timestamps=1 с нулевым revalidate_freq на высоконагруженном NFS.

Realpath cache

Битрикс активно ходит по путям /bitrix и /local. Усильте realpath cache в php.ini FPM:

realpath_cache_size = 4096k
realpath_cache_ttl  = 600

Это не замена OPcache, но снижает лишние stat() по файловой системе.

PHP Preloading (PHP 8+)

opcache.preload=/var/www/site/local/php_interface/preload.php
opcache.preload_user=www-data

В preload.php обычно подключают автолоад и набор «горячих» классов. Не тащите туда всё ядро подряд без измерений: ошибочный preload ломает старт FPM. Начните с малого набора и смотрите время первого запроса после рестарта.

Типичные ошибки на Битрикс-продакшне

  • После git pull «старый код» — validate_timestamps=0 и забыли reload FPM / opcache_reset.
  • Правили CLI-ini, а сайт на FPM — изменения не действуют; всегда смотрите phpinfo() через веб.
  • cache_full=1 — увеличьте memory и max_accelerated_files, иначе часть файлов не кешируется.
  • save_comments=0 — ломает аннотации/доктрину/некоторые библиотеки; для Битрикс лучше оставить 1.
  • Слишком большой max_children — уходит в swap, TTFB растёт, хотя OPcache «в зелёном».

Чеклист после настройки

  1. OPcache enabled в веб-phpinfo()
  2. Hit rate > 98% после прогрева
  3. Нет cache_full
  4. Понятен процесс сброса OPcache в CI/CD
  5. pm.max_children посчитан от RAM, не «на глаз»
  6. Realpath cache увеличен

OPcache и PHP-FPM — фундамент, на котором уже имеют смысл Redis, CDN и оптимизация SQL. Если этот слой кривой, остальные ускорения дают меньше эффекта, чем могли бы.