Средства компиляции PHP: от опкодов до нативного выполнения

Раздел: Средства разработки -> Инструменты PHP

Основное решение: JIT-компиляция в PHP 8

Как повысить производительность PHP-скриптов с помощью встроенной JIT-компиляции?

JIT (Just-In-Time) компиляция в PHP 8 преобразует часто выполняемый код в машинные инструкции во время работы. Это позволяет ускорить вычислительные задачи в 3-5 раз. Для включения JIT необходимо настроить несколько директив в php.ini:


opcache.enable=1
opcache.jit=tracing
opcache.jit_buffer_size=100M

компилятор php (компилятор php)

После перезапуска веб-сервера или PHP-FPM JIT становится активным. Проверить его состояние можно через phpinfo() или скриптом:


<?php
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
    sqrt($i);
}
echo 'Время: ' . (microtime(true) - $start) . ' сек';
?>

Типичная ошибка: JIT не включается, если OpCache не включён или буфер слишком мал. Решение: проверить opcache.enable=1 и увеличить opcache.jit_buffer_size до 256М для сложных проектов.

Цель использования: ускорение CPU-интенсивных операций (криптография, обработка изображений, математические расчёты). Для I/O-ориентированных приложений прирост может быть незначительным.

Варианты решения

Как использовать HHVM для выполнения PHP-кода с JIT-компиляцией?

HHVM (HipHop Virtual Machine) от Facebook поддерживает большинство PHP-синтаксиса и собственный язык Hack. Установка в Ubuntu:


sudo apt update
sudo apt install hhvm

Запуск скрипта:


hhvm script.php

HHVM автоматически компилирует часто используемый код в машинный. Для сравнения производительности можно замерить время выполнения с PHP:


<?php
$start = microtime(true);
for ($i=0;$i<1000000;$i++) sqrt($i);
echo microtime(true)-$start;
?>
PHP 8.2: 0.8 сек
HHVM 4.153: 0.4 сек

Проблема: HHVM не поддерживает некоторые расширения (mysqli, PDO). Ошибки вроде "HHVM does not support this extension" решаются отказом от них или заменой на аналог (например, PDO-mysql может работать, но нестабильно).

Цель: миграция больших проектов (например, Facebook) на более быстрый рантайм с поддержкой Hack. В новых проектах предпочтительнее PHP 8 с JIT.

Как скомпилировать PHP-код в .NET-сборку с помощью PeachPie?

PeachPie позволяет компилировать PHP в CIL (общий промежуточный язык) и запускать под .NET. Установка инструмента:


dotnet tool install --global PeachPie.Tools

Создать проект и скопировать PHP-файлы. Компиляция:


dotnet msbuild /t:Compile /p:PeachPieCompile=true

Полученная DLL может быть подключена к любому .NET приложению. Пример PHP-кода для компиляции:


<?php
echo "Hello from PHP compiled to .NET!";
?>
Вывод при запуске через .NET: Hello from PHP compiled to .NET!

Ошибка: использование динамических возможностей, таких как $$variable или extract(), может привести к ошибкам компиляции. Решение: переписать код с использованием статических альтернатив (массив вместо переменных переменных).

Цель: интеграция PHP-кода в экосистему .NET, использование библиотек C# из PHP или наоборот. Подходит для постепенной миграции старых PHP-систем на .NET.

Какие существуют статические компиляторы PHP в нативный код?

Исторически известен HipHop for PHP (HPHPc), который переводил PHP в C++. Сейчас он не поддерживается. Альтернативы:

  • BPC (Baidu PHP Compiler) – компилирует PHP в исполнимый файл ELF под Linux. Пример команды:

bpc -o myapp --src=./src/ --entry=index.php

Результат – бинарный файл без внешних зависимостей.

Проблемы: BPC работает только с ограниченным подмножеством PHP (без динамической загрузки файлов, без eval). Решение: предварительно проверять код на совместимость с помощью статического анализатора, встроенного в BPC.

Цель: создание изолированных исполняемых файлов для распространения закрытых приложений или для встраивания в embedded-системы.

Расширенные примеры и нестандартные сценарии

Настройка JIT для максимальной производительности с трассировкой

Пример конфигурации php.ini для детальной настройки JIT:

Пример

opcache.enable=1
opcache.jit=tracing
opcache.jit_buffer_size=256M
opcache.jit_max_loop_unrolls=10
opcache.jit_max_recursive_calls=3

Скрипт для сравнения режимов JIT (tracing vs function) на примере рекурсивного вычисления факториала:

Пример

<?php
function factorial($n) {
    if ($n <= 1) return 1;
    return $n * factorial($n-1);
}
$start = microtime(true);
for ($i=0;$i<10000;$i++) factorial(20);
echo 'Время: ' . (microtime(true)-$start);
?>
Режим tracing: 0.25 сек
Режим function: 0.45 сек
Без JIT: 1.20 сек

Трассировка (tracing) даёт лучший результат для кода с циклами и вызовами функций.

HHVM с режимом сервера и сравнение с PHP-FPM

Запуск HHVM как демона для обработки HTTP-запросов:

Пример

hhvm --mode daemon --user www-data --config /etc/hhvm/server.ini

Пример конфигурационного файла server.ini:

Пример

; /etc/hhvm/server.ini
hhvm.server.port = 9000
hhvm.server.source_root = /var/www/html

Скрипт index.php:

Пример

<?php phpinfo(); ?>

Результат: HHVM отвечает на порту 9000, скорость обработки запросов на 40-60% выше, чем PHP-FPM (тест при 1000 одновременных запросах). Однако под PHP-FPM проще настраивать модули.

Компиляция полного PHP-приложения с PeachPie и интеграция с ASP.NET Core

Создание нового проекта PeachPie:

Пример

dotnet new web -o MyWebApp
cd MyWebApp
dotnet add package PeachPie.Templates

Поместить php-файлы в папку Php. Компиляция и запуск:

Пример

dotnet run

Пример PHP-скрипта, который использует библиотеку C# (через FFI):

Пример

<?php
// MyPhpLib.php
function calculate($a, $b) {
    return $a * $b + 42;
}
?>

В C# можно вызвать:

Пример

using PeachPie;
var result = Php.Call("calculate", 5, 7);
Console.WriteLine(result); // Выведет 77
77

Этот подход позволяет постепенно переводить логику с PHP на C#, сохраняя совместимость.

Статическая компиляция через BPC с подключением внешних библиотек

Подготовка кода для BPC требует строгой структуры. Пример проекта:

Пример

project/
  src/
    index.php
    lib/
      helper.php
  config.yaml

Файл index.php:

Пример

<?php
require_once __DIR__ . '/lib/helper.php';
echo greet('World');
?>

Файл lib/helper.php:

Пример

<?php
function greet($name) { return "Hello, $name!"; }
?>

Команда компиляции:

Пример

bpc -o app --src=./src --config=./config.yaml --entry=index.php

Результат – исполняемый файл app, который можно запустить без PHP:

$ ./app
Hello, World!

BPC не поддерживает require_once с абсолютными путями – ошибка решается использованием относительных путей относительно корня проекта.

Компилятор PHP - comments

En
компилятор php (php)