OPcache і JIT

OPcache працює з OxPHP одразу, без додаткових дій. Усі робочі потоки PHP спільно використовують один сегмент пам’яті OPcache. Скрипти компілюються один раз під час першого виконання, а далі кожен робочий потік отримує їх із кешу. Щоб увімкнути це спільне використання, нічого спеціально налаштовувати не потрібно.

Як OPcache працює з OxPHP

OxPHP реєструється як іменований SAPI, і OPcache поводиться з ним так само, як з іншими серверними SAPI. Основні особливості:

  • Спільний кеш для всіх робочих потоків: усі робочі потоки PHP використовують той самий кеш скомпільованих опкодів. Один потік компілює файл — виграють усі.
  • Жодної компіляції на кожен запит: після першого запиту до кожного скрипту наступні запити повністю пропускають етап розбору й компіляції.
  • opcache.enable_cli не впливає на OxPHP. Цей параметр стосується лише SAPI з назвами cli і phpdbg. OxPHP реєструється з назвою SAPI cli-server, тож OPcache керується виключно через opcache.enable. Параметр opcache.enable_cli корисний, якщо ви запускаєте PHP CLI в тому самому контейнері (наприклад, для міграцій або команд Artisan). Офіційний образ OxPHP постачає PHP CLI разом із бінарним файлом сервера, тож ви можете встановити opcache.enable_cli=1, якщо вашим CLI-скриптам кешування піде на користь.

Щоб увімкнути OPcache, достатньо мінімум:

ini
[opcache] opcache.enable=1
Note

Офіційний Docker-образ OxPHP побудовано на php:*-zts-alpine, де OPcache статично вкомпільовано в бінарний файл PHP. НЕ додавайте zend_extension=opcache до свого INI-файлу. Розширення вже завантажене, і цей рядок спричинятиме попередження під час кожного запуску PHP. Потрібна лише секція конфігурації [opcache].

Рекомендовані налаштування для продакшну

Ці налаштування оптимізовано для розгортання в контейнерах у продакшні, де PHP-файли не змінюються під час роботи. Для максимальної пропускної здатності вимкніть перевірку часових позначок. Щоб також компілювати файли під час запуску, додайте два параметри з розділу Попереднє завантаження.

ini
[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, щоб під час налагодження отримувати зрозуміліші трасування стека.

ini
[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 перевіряє часову позначку включеного файлу щонайбільше раз на revalidate_freq секунд, тож зміни коду підхоплюються, щойно мине це вікно, без перезапуску контейнера й без зовнішнього демона для відстеження файлів. Використовуйте revalidate_freq=0 для негайної перевірки під час кожного включення (найвища точність, трохи більше вводу-виводу) або revalidate_freq=2, щоб розподілити вартість перевірок. Наведене вище значення за замовчуванням — вдалий компроміс, особливо якщо ваш DOCUMENT_ROOT розташовано на повільному bind-монтуванні (Docker на macOS/Windows).

Що НЕ перезавантажується через validate_timestamps

Деякі види змін усе одно потребують перезапуску контейнера (або перезапуску робочого процесу) навіть із validate_timestamps=1:

  • Попередньо завантажені файли (opcache.preload) під’єднуються до сервера під час запуску й ніколи не перевіряються повторно. Змінили попередньо завантажений файл — перезапустіть контейнер.
  • Стан ініціалізації Worker Mode — у Worker Mode автозавантажувач, DI-контейнер і будь-які об’єкти, створені в зовнішній області видимості, живуть у пам’яті робочого процесу. OPcache перекомпілює змінені файли класів, але робочий процес не виконає свою ініціалізацію повторно. Для циклів робочих процесів під час розробки викликайте Worker::scheduleExit() наприкінці кожного запиту (наприклад, за прапорцем середовища OXPHP_DEV), щоб перезапустити робочий процес: він знову виконає зовнішню область видимості й підхопить усі зміни.
  • Кеші на рівні фреймворку — скомпільований контейнер Symfony, кеш маршрутів/конфігурації/представлень Laravel, оптимізована карта класів Composer. Це файли .php, які OPcache перевіряє повторно, але значення в них посилаються на застарілі шляхи класів або ідентифікатори контейнера. Виконайте команду фреймворку cache:clear; самого OPcache недостатньо.
  • Не-PHP файли — .env, composer.json, конфігурація YAML/JSON, файли шаблонів, що компілюються поза OPcache. OPcache відстежує лише файли, які сам скомпілював; усе інше потребує перезапуску.

JIT-компіляція

JIT-компілятор OPcache перетворює опкоди PHP на нативний машинний код під час виконання. Для найкращої оптимізації використовуйте режим tracing:

ini
opcache.jit=tracing opcache.jit_buffer_size=64M

JIT дає найбільший виграш для PHP-коду, обмеженого процесором: циклів з інтенсивною математикою, обробки рядків, роботи із зображеннями та рендерингу шаблонів. Для застосунків, обмежених вводом-виводом, які більшу частину часу чекають на запити до бази даних чи виклики зовнішніх API, покращення мінімальне.

Щоб вимкнути JIT:

ini
opcache.jit=disable opcache.jit_buffer_size=0

Попереднє завантаження

Попереднє завантаження OPcache компілює й кешує PHP-файли під час запуску сервера, ще до обробки будь-яких запитів. Це повністю усуває вартість компіляції на першому запиті й робить класи та функції доступними глобально без жодних накладних витрат на require чи автозавантаження.

Налаштуйте попереднє завантаження у своєму INI-файлі:

ini
opcache.preload=/var/www/html/preload.php opcache.preload_user=www-data

Створіть скрипт preload.php, який завантажує файли, що використовуються найчастіше:

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');
Note

Попередньо завантажені класи й функції постійно доступні для всіх запитів. Змінити їх без перезапуску сервера неможливо.

Worker Mode і попереднє завантаження

Якщо ви використовуєте Worker Mode, ваш застосунок і так ініціалізується один раз: автозавантажувач, конфігурація та з’єднання з базою даних зберігаються між запитами. Попереднє завантаження OPcache доповнює це, усуваючи накладні витрати на компіляцію опкодів, але не замінює ініціалізацію застосунку. Ці два механізми працюють незалежно й можуть використовуватися разом.

Застосування конфігурації PHP

OxPHP читає конфігурацію PHP зі стандартного каталогу conf.d. Щоб передати власний INI-файл, використайте Docker-том або інструкцію COPY.

bash
docker run -p 80:80 \ -v ./custom.ini:/usr/local/etc/php/conf.d/custom.ini:ro \ ghcr.io/oxphp/oxphp:0.13.0

Моніторинг стану кешу

Щоб переконатися, що OPcache працює, перевірте його поточний стан із PHP:

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.

Промпти для вашого агента

Ці промпти розраховані на агента з під’єднаним MCP-сервером документації OxPHP — потрібні сторінки він прочитає сам.

prompt
Налаштуй OPcache під фактичний обсяг коду цього репозиторію та під те, як збирається його образ. Прочитай сторінку `php/opcache` через MCP-сервер документації OxPHP. Порахуй файли `.php`, які постачає цей проєкт, щоб визначити `max_accelerated_files` і `memory_consumption`, і вибери `validate_timestamps` залежно від того, чи мій Dockerfile вбудовує код в образ, чи його накладає bind-монтування під час виконання.

Дивіться також