OPcache и JIT
OPcache работает с OxPHP из коробки. Все потоки-воркеры PHP используют общий сегмент памяти OPcache. Скрипты компилируются один раз при первом выполнении, а затем каждый воркер обслуживает их из кеша. Для включения этого совместного использования никакой особой настройки не требуется.
Как OPcache работает с OxPHP
OxPHP регистрируется как именованный SAPI, и OPcache обращается с ним так же, как с другими серверными SAPI. Ключевые особенности:
- Общий кеш для всех воркеров: все потоки-воркеры PHP используют один и тот же кеш скомпилированных опкодов. Один воркер компилирует файл — выигрывают все воркеры.
- Никакой компиляции на каждый запрос: после первого запроса к каждому скрипту последующие запросы полностью пропускают этапы парсинга и компиляции.
opcache.enable_cliне влияет на OxPHP. Эта настройка применяется только к SAPI с именамиcliиphpdbg. OxPHP регистрируется под именем SAPIcli-server, поэтому OPcache управляется исключительно черезopcache.enable. Настройкаopcache.enable_cliполезна, если вы запускаете PHP CLI в том же контейнере (например, для миграций или команд Artisan). Официальный образ OxPHP поставляется с PHP CLI рядом с бинарником сервера, поэтому вы можете установитьopcache.enable_cli=1, если вашим CLI-скриптам полезно кеширование.
Чтобы включить OPcache, минимально необходимо:
[opcache]
opcache.enable=1Официальный Docker-образ OxPHP основан на php:*-zts-alpine, где OPcache статически вкомпилирован в бинарник PHP. НЕ добавляйте zend_extension=opcache в свой INI-файл. Расширение уже загружено, и добавление этой строки вызовет предупреждение при каждом запуске PHP. Нужна только секция конфигурации [opcache].
Рекомендуемые настройки для продакшена
Эти настройки оптимизированы для развёртывания в контейнерах на продакшене, где PHP-файлы не меняются во время работы. Для максимальной пропускной способности отключите проверку временных меток и включите предзагрузку скомпилированных файлов при запуске.
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.file_update_protection=0
opcache.jit_buffer_size=64M
opcache.jit=tracing| Настройка | Рекомендуемое значение | Описание |
|---|---|---|
memory_consumption |
128 |
Разделяемая память в МБ для скомпилированных скриптов. Увеличьте, если opcache_get_status() показывает мало свободной памяти. |
interned_strings_buffer |
16 |
Память в МБ для интернированных строк, разделяемых между всеми воркерами. |
max_accelerated_files |
10000 |
Максимальное число кешируемых скриптов. Установите значение выше общего количества ваших .php-файлов. |
validate_timestamps |
0 |
При значении 0 OPcache никогда не проверяет файловую систему на изменения. Чтобы применить изменения в коде, перезапустите контейнер или вызовите opcache_reset(). |
revalidate_freq |
0 |
Интервал в секундах между проверками файловой системы. Не действует при validate_timestamps=0. |
file_update_protection |
0 |
Сколько секунд после изменения файла должно пройти, прежде чем файл станет пригоден для кеширования. Установите 0, чтобы кешировать сразу при запуске. |
Настройки для разработки
Для разработки включите проверку временных меток, чтобы изменения в коде вступали в силу без перезапуска контейнера. Отключите JIT, чтобы получать более понятные трассировки стека при отладке.
[opcache]
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.jit_buffer_size=0
opcache.jit=disableПри validate_timestamps=1 OPcache проверяет время изменения файлов каждые revalidate_freq секунд. Это добавляет небольшие накладные расходы на каждый запрос, но позволяет редактировать PHP-файлы и видеть изменения при следующем запросе.
Это рекомендуемая стратегия перезагрузки в режиме разработки для OxPHP. OPcache выполняет проверку встроенно при каждом include, поэтому правки в коде подхватываются при следующем запросе без перезапуска контейнера и без внешнего демона-наблюдателя за файлами. Используйте revalidate_freq=0 для немедленного stat при каждом include (максимальная точность, чуть больше операций ввода-вывода) или revalidate_freq=2, чтобы амортизировать стоимость stat. Показанное выше значение по умолчанию — хороший баланс, особенно если ваш DOCUMENT_ROOT находится на медленном bind-mount (Docker на macOS/Windows).
Что НЕ перезагружается при validate_timestamps
Несколько категорий изменений всё равно требуют перезапуска контейнера (или пересоздания воркера) даже при validate_timestamps=1:
- Предзагруженные файлы (
opcache.preload) подключаются к серверу при запуске и никогда не проверяются повторно. Отредактировали предзагруженный файл — перезапустите контейнер. - Состояние инициализации в режиме воркеров — в режиме воркеров автозагрузчик, DI-контейнер и любые объекты, созданные во внешней области видимости, живут в памяти воркера. OPcache перекомпилирует изменённые файлы классов, но воркер не выполнит повторно свою инициализацию. Для циклов воркеров в разработке вызывайте
Worker::scheduleExit()в конце каждого запроса (например, под флагом окруженияOXPHP_DEV), чтобы пересоздать воркер — это заново выполнит внешнюю область видимости и подхватит все изменения. - Кеши на уровне фреймворка — скомпилированный контейнер Symfony, кеш маршрутов/конфигурации/представлений Laravel, оптимизированный classmap Composer. Это
.php-файлы, которые OPcache проверяет повторно, но значения внутри них ссылаются на устаревшие пути классов или идентификаторы контейнера. Выполните командуcache:clearвашего фреймворка — одного OPcache недостаточно. - Не-PHP-файлы —
.env,composer.json, конфигурация YAML/JSON, файлы шаблонов, компилируемые вне OPcache. OPcache отслеживает только те файлы, которые он скомпилировал; всё остальное требует перезапуска.
JIT-компиляция
JIT-компилятор OPcache во время выполнения транслирует опкоды PHP в нативный машинный код. Для наилучшей оптимизации используйте режим tracing:
opcache.jit=tracing
opcache.jit_buffer_size=64MJIT даёт наибольший выигрыш для PHP-кода, ограниченного производительностью процессора (CPU-bound): циклы с интенсивными вычислениями, обработка строк, работа с изображениями и рендеринг шаблонов. Для приложений, ограниченных вводом-выводом (I/O-bound), которые большую часть времени ждут ответа от запросов к базе данных или внешних API-вызовов, улучшение минимально.
Чтобы отключить JIT:
opcache.jit=disable
opcache.jit_buffer_size=0Предзагрузка
Предзагрузка OPcache компилирует и кеширует PHP-файлы при запуске сервера, до обработки каких-либо запросов. Это полностью устраняет стоимость компиляции при первом запросе и делает классы и функции доступными глобально без каких-либо накладных расходов на require или автозагрузку.
Настройте предзагрузку в своём INI-файле:
opcache.preload=/var/www/html/preload.php
opcache.preload_user=www-dataСоздайте скрипт preload.php, который загружает наиболее часто используемые файлы:
<?php
// preload.php — runs once at server startup
require __DIR__ . '/vendor/autoload.php';
// Preload framework core files
$files = glob(__DIR__ . '/vendor/symfony/http-kernel/**.php');
foreach ($files as $file) {
opcache_compile_file($file);
}
// Preload hot application paths
opcache_compile_file(__DIR__ . '/src/Controller/ApiController.php');
opcache_compile_file(__DIR__ . '/src/Service/UserService.php');Предзагруженные классы и функции постоянно доступны всем запросам. Их нельзя изменить без перезапуска сервера.
Если вы используете режим воркеров, ваше приложение уже инициализируется один раз: автозагрузчик, конфигурация и соединения с базой данных сохраняются между запросами. Предзагрузка OPcache дополняет это, устраняя накладные расходы на компиляцию опкодов, но не заменяет инициализацию приложения. Эти два механизма работают независимо и могут использоваться совместно.
Применение конфигурации PHP
OxPHP читает конфигурацию PHP из стандартного каталога conf.d. Чтобы предоставить свой собственный INI-файл, используйте Docker-том или инструкцию COPY.
docker run -p 80:80 \
-v ./custom.ini:/usr/local/etc/php/conf.d/custom.ini:ro \
ghcr.io/oxphp/oxphp:0.10.0FROM ghcr.io/oxphp/oxphp:0.10.0
COPY custom.ini /usr/local/etc/php/conf.d/custom.ini
COPY --chown=www-data:www-data . /var/www/htmlservices:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "80:80"
volumes:
- ./custom.ini:/usr/local/etc/php/conf.d/custom.ini:ro
- ./src:/var/www/htmlМониторинг состояния кеша
Проверьте текущее состояние OPcache из PHP, чтобы убедиться, что он работает:
<?php
$status = opcache_get_status();
echo "Cached scripts: " . $status['opcache_statistics']['num_cached_scripts'] . "\n";
echo "Cache hits: " . $status['opcache_statistics']['hits'] . "\n";
echo "Cache misses: " . $status['opcache_statistics']['misses'] . "\n";
echo "Free memory: " . $status['memory_usage']['free_memory'] . " bytes\n";Если free_memory стабильно мало, увеличьте opcache.memory_consumption.
Смотрите также
- Руководство по Docker -- настройка контейнеров и монтирование файлов конфигурации
- Справочник по конфигурации -- переменные окружения для OxPHP
- Режим воркеров -- постоянные процессы PHP, получающие наибольшую выгоду от OPcache