OPcache и JIT-компиляция
Ускоряйте PHP с помощью кэширования байткода и JIT
«OPcache и JIT-компиляция» — бесплатный урок PHP Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения PHP Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс PHP Academy содержит 4 уроков всего.
Кэширование компиляции
Кэширование опкодов сохраняет скомпилированные опкоды в общей памяти, поэтому PHP не выполняет лексический и синтаксический анализ и компиляцию при каждом запросе. Кроме того, компиляция точно вовремя преобразует горячие опкоды в машинный код. Вместе эти механизмы составляют основу производительности PHP.
В этом уроке рассматриваются настройка кэширования опкодов, предзагрузка и настройка компиляции точно вовремя.
Что делает кэширование опкодов
Скомпилированный op_array каждого файла кэшируется в сегменте общей памяти, используемом всеми рабочими процессами FPM. Запрос, попавший в кэш, напрямую повторно использует опкоды. При первой компиляции файла кэширование также запускает оптимизатор (свёртка констант, удаление мёртвого кода, объединение опкодов).
; Core OPcache config (php.ini)
opcache.enable = 1
opcache.memory_consumption = 256 ; MB of shared memory
opcache.interned_strings_buffer = 16 ; MB for interned strings
opcache.max_accelerated_files = 20000 ; cap on cached scriptsПроверка временных меток
validate_timestamps определяет, проверяет ли кэширование опкодов время изменения файлов. В разработке оставьте эту настройку включённой и задайте небольшое значение revalidate_freq; в рабочей среде установите 0, чтобы PHP никогда не проверял файлы, а при развёртывании очищайте кэш или пересобирайте образ.
; Production: never re-stat files
opcache.validate_timestamps = 0
; Development: check every 2 seconds
; opcache.validate_timestamps = 1
; opcache.revalidate_freq = 2Просмотр кэша
opcache_get_status() сообщает о доле попаданий, использовании памяти и кэшированных сценариях; opcache_get_configuration() показывает настройки. Низкая доля попаданий или частые перезапуски означают, что памяти слишком мало или файлов слишком много.
<?php
if (function_exists('opcache_get_status')) {
$s = opcache_get_status(false);
if ($s) {
printf("hits: %d\n", $s['opcache_statistics']['hits']);
printf("misses: %d\n", $s['opcache_statistics']['misses']);
printf("hit %%: %.2f\n", $s['opcache_statistics']['opcache_hit_rate']);
printf("used: %.1f MB\n", $s['memory_usage']['used_memory'] / 1048576);
} else {
echo "OPcache enabled but no status (likely CLI)\n";
}
} else {
echo "OPcache not available\n";
}
?>Предзагрузка
Предзагрузка (PHP 7.4+) один раз компилирует набор классов и функций при запуске сервера и хранит их в памяти постоянно, делая их доступными каждому запросу без автозагрузки и связывания для каждого запроса. Укажите в opcache.preload сценарий, подключающий файлы для предварительного прогрева.
; php.ini
opcache.preload = /app/preload.php
opcache.preload_user = www-dataНаписание сценария предзагрузки
Сценарий предзагрузки выполняется в главном процессе. Используйте opcache_compile_file(), чтобы загрузить классы без их выполнения, или просто подключите их. Платформы генерируют список предзагрузки; вот его примерная структура.
<?php
// preload.php — runs once at startup
$dir = '/app/src';
$rii = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir)
);
foreach ($rii as $file) {
if ($file->getExtension() === 'php') {
// Compiles + links the class into shared memory
opcache_compile_file($file->getPathname());
}
}
?>Знакомство с компиляцией точно вовремя
Даже при кэшировании опкодов VM всё ещё интерпретирует их. Компиляция точно вовремя преобразует горячие последовательности опкодов в машинные инструкции CPU, устраняя накладные расходы на диспетчеризацию VM. Выигрыш велик для числового кода, ограниченного производительностью CPU, и умерен для обычных веб-приложений, ограниченных операциями ввода-вывода (которые тратят время на базу данных и сеть, а не на CPU).
Настройка компиляции точно вовремя
Компиляция точно вовремя работает внутри кэширования опкодов, поэтому кэширование опкодов должно быть включено. opcache.jit_buffer_size выделяет место для сгенерированного машинного кода (значение 0 отключает компиляцию точно вовремя). opcache.jit — это режим из четырёх цифр, управляющий условием запуска и стратегией оптимизации.
; Enable JIT (requires opcache.enable=1)
opcache.jit_buffer_size = 128M
opcache.jit = tracing ; alias for 1254, the common default
; The 4 digits CRTO mean:
; C - CPU optimization flags
; R - register allocation
; T - trigger (when to JIT)
; O - optimization levelТрассирующая и функциональная компиляция точно вовремя
Есть две стратегии: функциональная компиляция точно вовремя (режим 1205) компилирует целые функции при первом вызове; трассирующая компиляция точно вовремя (1254, псевдоним по умолчанию tracing) профилирует выполнение и компилирует горячие циклы и пути, часто показывая лучшие результаты, поскольку специализируется на наблюдавшихся типах. Трассирующая стратегия рекомендуется по умолчанию.
; Tracing JIT (recommended) — compiles hot traces
opcache.jit = tracing
; Function JIT — compiles entire functions when first called
; opcache.jit = function
; Disable JIT but keep opcode cache
; opcache.jit_buffer_size = 0Измерение влияния компиляции точно вовремя
Компиляция точно вовремя особенно эффективна в интенсивных числовых циклах. Этот автономный тест (внутренний цикл, напоминающий вычисления Мандельброта) относится к тем рабочим нагрузкам, ограниченным производительностью CPU, где компиляция точно вовремя может существенно сократить время выполнения; запустите его с включённым и выключенным jit_buffer_size, чтобы сравнить результаты.
<?php
function mandelEscape(float $cr, float $ci, int $max): int {
$zr = 0.0; $zi = 0.0; $n = 0;
while ($n < $max && ($zr * $zr + $zi * $zi) <= 4.0) {
$t = $zr * $zr - $zi * $zi + $cr;
$zi = 2.0 * $zr * $zi + $ci;
$zr = $t;
$n++;
}
return $n;
}
$start = hrtime(true);
$sum = 0;
for ($y = 0; $y < 200; $y++) {
for ($x = 0; $x < 200; $x++) {
$sum += mandelEscape($x / 100 - 2, $y / 100 - 1, 256);
}
}
printf("sum=%d time=%.2f ms\n", $sum, (hrtime(true) - $start) / 1e6);
?>Когда не стоит ожидать прироста
В обычном запросе, который обращается к базе данных, отображает шаблон и возвращает JSON, CPU выполняет мало простых арифметических операций — компиляция точно вовремя может дать прирост в несколько процентов или не дать его вовсе. Сначала сосредоточьтесь на кэшировании опкодов, предзагрузке и эффективном использовании базы данных и кэша. Настройку компиляции точно вовремя оставьте для обработки изображений, математических вычислений, анализаторов и другого вычислительно сложного кода.
Быстрая проверка
Что даёт предзагрузка по сравнению с обычным кэшированием?
Повторение
Кэширование сохраняет скомпилированные массивы операций в общей памяти и запускает оптимизатор; в рабочей среде установите validate_timestamps=0 и правильно задайте размеры memory_consumption/max_accelerated_files. Предзагрузка сохраняет выбранные классы в памяти уже при запуске. Компиляция точно вовремя (внутри кэширования, требует jit_buffer_size) преобразует горячий код в машинные инструкции — она значительно ускоряет вычисления, ограниченные CPU, но почти не помогает веб-приложениям, ограниченным вводом-выводом. Для проверки используйте opcache_get_status().
Часто задаваемые вопросы
Урок «OPcache и JIT-компиляция» бесплатный?
Да — полный текст урока «OPcache и JIT-компиляция» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс PHP Academy, подпишись на CoddyKit PRO. Курс PHP Academy содержит 4 уроков всего.
Чему я научусь в уроке «OPcache и JIT-компиляция»?
Ускоряйте PHP с помощью кэширования байткода и JIT Ты практикуешь PHP Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать PHP Academy?
Предыдущий опыт не требуется. PHP Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «OPcache и JIT-компиляция»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке PHP Academy?
Да. Каждый урок PHP Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Как работает Zend Engine
- Управление памятью и сборка мусора
- OPcache и JIT-компиляция
- Написание базового расширения PHP на C