0Pricing
PHP Academy · Урок

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 — локальная установка не требуется.

Все уроки этого курса

  1. Как работает Zend Engine
  2. Управление памятью и сборка мусора
  3. OPcache и JIT-компиляция
  4. Написание базового расширения PHP на C
← Назад к PHP Academy