Что такое OPcache и почему он особенно важен для Битрикс
PHP - интерпретируемый язык. При каждом запросе сервер читает .php-файл, парсит его, компилирует в байткод (opcodes) и только потом выполняет. На нагруженном сайте это происходит тысячи раз в секунду с одними и теми же файлами.
OPcache решает эту проблему радикально: сохраняет скомпилированный байткод в оперативной памяти. При следующем запросе PHP берёт готовый байткод прямо из памяти, минуя этапы чтения файла и компиляции. Результат - в 2-5 раз быстрее на реальных проектах.
Для Битрикса это особенно критично. Даже простая страница каталога подключает сотни файлов ядра, компонентов и шаблонов. Без OPcache каждый из них компилируется заново при каждом хите. Так что включение и правильная настройка кеша - это первое, что нужно сделать перед любой другой оптимизацией.
Еще есть старая, но не безполезная заметка: Ускорение 1С-Битиркс
Конфиг OPcache
Вот набор настроек, который хорошо работает на боевых Битрикс-серверах:
opcache.enable=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=50000
opcache.revalidate_freq=0
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.enable_cli=1
Кратко по каждому параметру:
- opcache.enable=1 - включает OPcache (по умолчанию выключен или зависит от сборки)
- opcache.memory_consumption=512 - 512 МБ под хранение байткода в памяти
- opcache.interned_strings_buffer=32 - 32 МБ под интернированные строки (имена функций, классов и т.д.)
- opcache.max_accelerated_files=50000 - максимальное кол-во файлов в кеше; для Битрикса меньше 10000 не ставить
- opcache.revalidate_freq=0 - как часто (в секундах) проверять актуальность кеша;
0в связке сvalidate_timestamps=0означает «никогда» - opcache.validate_timestamps=0 - главный виновник проблем на разработке; подробнее ниже
- opcache.save_comments=1 - сохранять комментарии в байткоде; нужно для аннотаций
- opcache.fast_shutdown=1 - ускоренное освобождение памяти при завершении запроса
- opcache.enable_cli=1 - включить OPcache для CLI (полезно для консольных команд и крон-задач)
Почему validate_timestamps=0 ломает разработку
Вот что происходит с этой настройкой:
- PHP первый раз читает файл MyClass.php, компилирует его и сохраняет байткод в памяти.
- Вы меняете код в MyClass.php и сохраняете файл.
- PHP получает следующий запрос, идёт в OPcache - байткод там есть. Проверять файл на диске он не будет - validate_timestamps=0 ему запрещает.
- Выполняется старый код. Вы видите старый результат.
Пока не перезагрузите PHP-FPM или nginx - изменения не появятся. На продакшене это идеально: никакой лишней работы с диском, максимальная скорость. На локальной разработке - мучение.
Как исправить: конфиг для разработки
Нужно изменить две строчки в php.ini (или в отдельном файле /etc/php/conf.d/opcache-dev.ini):
// Разрешаем PHP проверять, изменился ли файл на диске
opcache.validate_timestamps=1
// Проверять при каждом запросе (0 = без задержки)
opcache.revalidate_freq=0
opcache.validate_timestamps=1 - возвращает PHP к нормальному поведению: перед использованием байткода из кеша он сверяет время изменения файла (mtime) с тем, что было при компиляции. Если файл изменился - перекомпилирует.
opcache.revalidate_freq=0 - определяет, как часто делать эту проверку. Значение 0 означает при каждом запросе. Да, чуть медленнее, зато всегда видите актуальный код сразу после сохранения. Для продакшена ставят 60 или 120 (секунды между проверками).
Prod vs Dev: сравнение настроек
| Параметр | Production | Development |
|---|---|---|
opcache.enable |
1 | 1 |
opcache.validate_timestamps |
0 | 1 |
opcache.revalidate_freq |
0 | 0 |
opcache.memory_consumption |
512 | 128 |
opcache.max_accelerated_files |
50000 | 10000 |
На разработке нет смысла выделять 512 МБ под кеш - снизьте до 128. Остальное оставьте как есть, чтобы среда максимально совпадала с боевым сервером.
Как найти нужный php.ini
Если используете MAMP, Valet, Docker или любой другой локальный стек - проверьте php.ini именно той версии PHP, которую использует ваш проект. Часто бывает несколько версий, и настройки применяются не к той, которую вы думаете.
Найти нужный файл проще всего так:
php --ini | grep "Loaded Configuration"
Или через phpinfo() в браузере - ищите строку Loaded Configuration File.
Realpath cache
PHP при каждом include резолвит путь к файлу через файловую систему: проверяет симлинки, существование директорий и т.д. Realpath cache хранит результаты этих проверок в памяти.
// Размер кеша путей. 4M - хороший старт для Битрикса
realpath_cache_size=4096K
// Время жизни записи в секундах. 600 = 10 минут
realpath_cache_ttl=600
На Битрикс-проектах с большим кол-вом файлов это даёт заметный эффект - особенно при первых запросах после сброса кешей.
PHP-FPM: правильный пул
OPcache работает в памяти процесса. Чем больше воркеров PHP-FPM, тем больше памяти уходит под кеш. Оптимально - статический пул с фиксированным кол-вом воркеров вместо динамического. В /etc/php/8.x/fpm/pool.d/www.conf:
pm = static
pm.max_children = 20
Воркеры считаются просто: RAM / средний размер одного PHP-процесса. Средний процесс Битрикса весит 80-120 МБ. На сервере с 4 ГБ RAM под PHP - это 30-40 воркеров.
Отключите ненужные расширения
Каждое загруженное расширение PHP добавляет накладные расходы при старте процесса. В стандартной сборке часто включено много лишнего. Для Битрикса реально нужны:
- mbstring
- curl
- gd (или imagick)
- zip
- pdo_mysql
- json
- opcache
Всё остальное - проверьте, действительно ли используется.
expose_php=Off
На скорость не влияет, но убирает заголовок X-Powered-By: PHP/x.x.x из всех ответов. Меньше информации для сканеров.
expose_php=Off
Все эти настройки работают в связке. OPcache убирает компиляцию, realpath cache убирает лишние обращения к файловой системе, правильный пул FPM не даёт памяти расползтись. Итог - стабильное время ответа даже под нагрузкой.