Перейти к содержимому

Акселератор PHP - размер кэша кода и сброс при выкладке

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

Решение

Проверяем, что акселератор работает

Смотрим, собран ли модуль и с какими числами:

Окно терминала
php -v # строка Zend OPcache означает, что модуль есть
php -i | grep -E 'opcache.(enable|memory_consumption|max_accelerated_files)'
# консоль показывает настройки CLI, у сайта они берутся из своего набора ini

Ставить отдельный акселератор не нужно: OPcache идёт в составе PHP, а старые APC и eAccelerator не дополняют его, а конфликтуют. Итоговое состояние для сайта показывает вкладка «Конфигурация» монитора производительности: отсутствие акселератора она отмечает как типичную ошибку настройки.

Кладём настройки туда, где они выживут

Правим отдельный файл, а не общий конфиг окружения:

; /etc/php.d/z_bx_custom.ini - переживает обновление BitrixVM
opcache.enable = 1
opcache.memory_consumption = 128 ; МБ разделяемой памяти под байт-код
opcache.max_accelerated_files = 100000 ; число слотов под файлы
opcache.revalidate_freq = 0 ; проверять правку без задержки

Стандартные конфиги окружения заменяются при обновлении, а служба автоподстройки bvat перетирает правки поверх. Файлы z_bx_custom.* она не трогает, поэтому настройка доживает до следующей версии окружения. После правки перезапускаем пул PHP: рабочие процессы читают ini только при старте.

Считаем размер под платформу

Считаем реальное число файлов проекта:

Окно терминала
# столько слотов акселератору нужно минимум, дальше добавляем запас на рост
find /home/bitrix/www -name '*.php' \
-not -path '*/bitrix/cache/*' -not -path '*/bitrix/managed_cache/*' | wc -l

Ядро с модулями и решениями маркетплейса даёт десятки тысяч файлов, поэтому слотов берут с запасом: технические требования называют сто тысяч. Память под байт-код начинают с 32-64 МБ и на крупных проектах поднимают до 128 МБ. Перекомпиляция забирает до 60% времени генерации страницы, и настроенный акселератор ускоряет сайт примерно втрое.

Смотрим занятость кэша и промахи

Проверяем, помещается ли код целиком в отведённую память:

$s = opcache_get_status(false);
$mem = $s['memory_usage'];
printf("память: %d из %d МБ\n", $mem['used_memory'] >> 20,
($mem['used_memory'] + $mem['free_memory']) >> 20);
printf("файлов: %d из %d, промахов: %d\n",
$s['opcache_statistics']['num_cached_scripts'],
$s['opcache_statistics']['max_cached_keys'],
$s['opcache_statistics']['misses']);

Растущее число промахов при заполненной памяти означает вытеснение: код вымывается и компилируется заново на следующем запросе. Лечится это увеличением памяти и числа слотов, а не сбросом кэша по расписанию.

Разводим боевой и стенд разработчика

Задаём проверку времени правки файлов по контурам:

; боевой: файлы меняются только выкладкой
opcache.validate_timestamps = 0
; стенд разработчика: правка видна на следующем запросе
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0

С нулём акселератор перестаёт опрашивать время правки каждого файла и экономит обращения к диску. Ценой этого правка не появляется на сайте, пока кэш кода не сброшен явно, - на стенде такое поведение только мешает.

Сбрасываем кэш кода при выкладке

Сбрасываем кэш тем же шагом, что и выкладываем файлы:

Окно терминала
# перезапуск пула чистит разделяемую память акселератора целиком
systemctl reload php-fpm
# либо дёргаем скрипт сброса из веб-процесса, а не из консоли
curl -s "https://example.ru/opcache-reset.php?key=$RESET_KEY"

Вызов opcache_reset() из консоли чистит кэш процесса CLI, а не пула веб-сервера: разделяемая память у них разная. Скрипт сброса закрываем секретным ключом и убираем из публичного доступа сразу после выкладки.

Типичные проблемы

Файлы на боевом новые, а сайт работает по-старому.

Кэш кода держит прежний байт-код, потому что проверка времени правки выключена. Сброс кэша встраивают в сценарий выкладки, а не делают руками через день.

Ошибка Class CUpdateExpertMode not found на странице обновлений.

Акселератор с opcache.validate_timestamps = 0 отдаёт закешированные старые файлы ядра. Помогает временное включение проверки времени правки в файле /etc/php.d/opcache.ini.

Число промахов растёт, хотя код не менялся.

В кэш кода попадают тысячи файлов из каталогов /bitrix/cache/ и /bitrix/managed_cache/. Основной код вытесняется ими и компилируется заново почти на каждом запросе к сайту.

После обновления окружения настройки акселератора откатились.

Правки лежали в общем конфиге окружения, который обновление заменяет своей версией. Единственный надёжный адрес для своих значений - отдельный файл z_bx_custom.ini.

При включённом акселераторе перестают работать решения маркетплейса.

Конфликт ищут отладкой по одному решению, а не общим выключением акселератора. Выключенный акселератор убирает симптом ценой троекратного замедления всех страниц сайта.

Частые вопросы

Как поставить акселератор на виртуальную машину Битрикс?

Ставить нечего: OPcache идёт в составе PHP и в окружении уже включён. Версию показывает php -v, а несколько акселераторов сразу не ускоряют сайт, а конфликтуют между собой.

Сколько памяти давать под кэш кода?

Обычному сайту хватает 32-64 МБ, крупному проекту дают 128 МБ. Ориентируются на занятую память и число промахов из opcache_get_status, а не на догадку по размеру каталога.

Почему после выкладки сайт отдаёт старый код?

На боевом обычно выключена проверка времени правки файлов. Кэш держит прежние версии, пока пул PHP не перезапущен или кэш не сброшен из веб-процесса скриптом.

Нужен ли акселератор на стенде разработчика?

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

Стоит ли исключать каталоги кэша платформы из акселератора?

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

Смежное

Первоисточник