Как PHP 8 стал быстрее: JIT, FFI и Preloading объясняет создатель JIT-компилятора

public

Автор: Дмитрий Стогов (Zend Technologies) · PHP Russia 2019


⚠️ Доклад 2019 года — за год до выхода PHP 8.0 (ноябрь 2020). Это анонс и технический разбор того, что готовилось. JIT, Preloading и FFI с тех пор вышли в стабильных версиях; суть механизмов Стогов объясняет точнее, чем большинство статей, написанных постфактум.


Дмитрий Стогов — один из ключевых людей за производительностью PHP. Автор Turck MMCache (eAccelerator), мейнтейнер Zend OPcache, лидер проекта PHPNG, который лёг в основу PHP 7 и дал двукратный прирост производительности без изменения синтаксиса. Теперь — лидер разработки JIT-компилятора для PHP 8. Когда он рассказывает о производительности PHP — это рассказ от человека, который её делал.

Три новых подсистемы PHP 8 — JIT, Preloading и FFI — Стогов рассматривает как взаимосвязанные. Все три направлены на производительность, но также открывают PHP новые области применения: писать системно-зависимые расширения прямо на PHP, подключать сторонние C-библиотеки, быстро прототипировать низкоуровневые вещи.

Кому смотреть: PHP-разработчикам, которые хотят понять JIT, FFI и Preloading не через «что делать в коде», а через «как это устроено и зачем» — от человека, который это написал.

Из этого можно взять в работу: если ваш PHP-сервис тяжело нагружен CPU-вычислениями (а не I/O) — именно для таких сценариев JIT даёт реальный прирост. Для типичного CRUD с базой данных эффект от JIT минимален — и Стогов об этом говорит честно.


Исторический слайд из доклада наглядно показывает траекторию производительности PHP: от PHP 5.0 до PHP 7.1 — кратный прирост на каждой мажорной версии, и PHPNG (PHP 7.0) как самый большой единовременный скачок. Стогов как автор PHPNG знает цену каждого из этих шагов изнутри.

JIT (Just-In-Time компилятор) — ключевое нововведение PHP 8. JIT компилирует часто исполняемый байткод в нативный машинный код во время выполнения, минуя Zend VM. Практически важная оговорка: JIT помогает CPU-bound задачам (математика, обработка данных). Типичный веб-запрос — это I/O-bound (база, сеть), и там JIT даёт меньше.

Preloading — механизм, позволяющий загрузить PHP-файлы (классы, функции) в память воркера один раз при старте, а не при каждом запросе. Совместно с JIT: скомпилированный нативный код остаётся в памяти между запросами.

FFI (Foreign Function Interface) — ext/ffi, автор которого сам Стогов. Позволяет вызывать функции из C-библиотек прямо из PHP-кода без написания C-расширения. Открывает возможность быстрого прототипирования и интеграции с системными библиотеками.