Компилируем быстрые консольные .exe приложения на PHP 8.1 в 2023 году, а почему бы и нет?

в 8:01, , рубрики: c++, dll, enigma, exe, ffi, jit, php, PHP 8, timeweb_статьи, WinAPI, Блог компании Timeweb Cloud, интерпретатор, компиляция, консоль, приложение, разработка под windows, утилита, франкенштейн
С каждым релизом PHP становится всё быстрее, а при включении JIT (Just-In-Time) компиляции, достигает почти отметок того же C.

image

У многих в своё время, наверное, было желание легкого написание консольных и оконных приложений. Ребята рунета иногда писали незаменимые приложения для решения мелких задач и делились на форумах, хотя некоторые из них и содержали костыли.

Однако времена меняются, и люди начали осознавать свои ошибки, переходя, скажем, на ООП.

Чтобы поностальгировать и продемонстрировать нового Франкенштейна, мы соберем полноценное консольное exe-приложение на PHP.

PHP — интерпретируемый язык, поэтому для работы нам просто необходимо иметь его бинарные файлы.

Для создания приложения нам понадобятся основной exe-файл и dll-библиотека движка. 32-битная версия PHP 8.1 занимает 7 Мб! Hello World с размером в 7 метров нам не подходит, согласитесь.

Следуя инструкции, мне удалось скомпилировать PHP без каких-либо дополнительных модулей, оставив только JIT и FFI (есть причина).

Размер получившихся файлов составил 5 Мб (x64), что уже не плохо, но недостаточно. Мы продолжим работать с x64, так как разница между ним и x86 составляет всего 100кб.

php.exe + php8.dll:

image

Теперь нам нужен PHP-код для нашего приложения.

Ради примера возьмём скрипт Zend Benchmark и добавим несколько аргументов командной строки для тестов.

Чтобы упаковать наше приложение в один файл, мы будем использовать бесплатную утилиту Enigma Virtual Box.

Но для этого Энигме нужен главный обработчик, который вызовет интерпретатор, но программировать на другом языке мы не будем, так как полагаемся только на PHP. :)

Используя BatToExe, мы вызываем интерпретатор из каталога %TEMP%. Позже Энигма позаботится, чтобы он оказался там.

image

%1 %2 — это количество аргументов, которые мы собираемся передать.

Выбираем обработчик, забрасываем наши бинарники с исходниками в окно Энигмы, используем папку %Temp Folder%. В Files Option кликаем на галочку компрессии.

В свойствах файлов по Методу Виртуализации ставим на -Запись если не существует-, сам скрипт советую ставить на -Запись всегда-, чтобы легче было дебажить код. Бинарником PHP является файл render.exe, скрипт exe.c.

image

Скомпилировав приложение мы получаем портативный файл, который весит 2.9 Мб!

Если бы мы пошли дальше и убрали все ненужные встроенные зависимости, а также написали бы легкий обработчик, который самостоятельно распаковывает архив, то, возможно, размер приложения уменьшился бы до сотен килобайтов (отпишитесь, если знаете такой).

Сжатый .7z архив с нынешними бинарниками весит всего 1.5 Мб.

Для сравнения, скомпилированный Hello World бинарник Go приложения, весит 1.2 Мб.

Тестируем:

image

Работает как часы, чтобы вы понимали про заявленную скорость ассемблер кода генерируемым JIT, моя машина проходит бенчмарк за 0.7с, при выключенном же JIT, она просядает до 2.4с.
Реализовать параллельность для ресурсоёмких вычислительных операций не проблема (функции popen() / proc_open), можно также воспользоваться готовыми библиотеками, как amphp/parallel.

Запуск самих приложений быстрый и составляет менее секунды.

Вычислим ещё корневой Merkle хеш большого файла:

image

Вы не забыли про FFI?

Благодаря этому расширению мы можем писать C код прямо в PHP, подключать dll библиотеки, создавать WinAPI приложения, вот пример кода MessageBox:

<?php
$ffi = FFI::cdef("
    int MessageBoxA(void*, const char*, const char*, int);
", "user32.dll");

$ffi->MessageBoxA(null, "Hello!", "Habr", 0);
?>

А вот результат:

image

Вывод:

Писать простые исполняемые приложения на PHP можно. Они могут выступать бэкенд утилитами для графических обёрток, но не следует этого делать, поскольку PHP отлично проявил себя в web-разработке, а не в десктоп-решениях.

Эксперименты на сырой платформе могут привести к проблемам.

Автор:
penetration

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js