TypePHP abre un camino poco habitual para el ecosistema PHP: compilar código PHP por adelantado a código máquina nativo, sin pasar después por los opcodes de Zend. El proyecto, desarrollado por el equipo de Swoole, toma PHP como lenguaje de entrada, genera C++17 y termina produciendo ejecutables, extensiones PHP o bibliotecas compartidas que corren directamente sobre el procesador.
Lo esencial en 20 segundos
- TypePHP es un compilador AOT (ahead-of-time) que convierte PHP en C++17 y de ahà en código máquina.
- Puede generar ejecutables, extensiones PHP y bibliotecas compartidas.
- El propio compilador está escrito en PHP y es capaz de compilarse a sà mismo.
- Sus benchmarks internos muestran mejoras de entre 6,5 y 8 veces en pruebas de PHP.
- Por ahora no promete compatibilidad con cualquier aplicación PHP existente.
Lo interesante de la propuesta es que no intenta sustituir PHP por otro lenguaje. Se sigue escribiendo PHP, aunque el desarrollador puede añadir tipos y estructuras de datos concretas cuando necesita más rendimiento.
Eso aleja bastante a TypePHP de proyectos como TypeScript. TypeScript acaba convertido de nuevo en JavaScript para correr dentro de un motor JavaScript, mientras que TypePHP lleva parte del código hasta instrucciones nativas que ejecuta la CPU directamente.
Tampoco es una comparación exacta con el JIT de PHP: OPcache, el JIT y TypePHP actúan en fases distintas y persiguen objetivos distintos.
De PHP a C++17 y de ahà a código máquina
PHP transforma normalmente el código fuente en opcodes que ejecuta el Zend Engine. OPcache evita repetir parte de ese trabajo guardando el bytecode ya compilado, y el JIT que llegó con PHP 8 puede convertir ciertas partes en código máquina durante la ejecución.
TypePHP hace ese trabajo antes, no durante: lo resuelve antes de que la aplicación se ejecute.
De forma simplificada, el proceso queda asÃ:
PHP
?
Parseo y validación
?
C++17
?
Compilador nativo
?
Código máquina
El proceso real incluye además declaraciones .stub.php, fuentes opcionales en C o C++, cachés de objetos reutilizables y cabeceras precompiladas.
Según la documentación del proyecto, TypePHP puede producir hoy varios tipos de salida:
| Modo | Salida | Uso tÃpico |
|---|---|---|
bin | Ejecutable nativo | Herramientas CLI, servicios y aplicaciones independientes |
ext | Extensión .so o .dll | Añadir código compilado a PHP |
lib | Biblioteca compartida | Reutilizar APIs compiladas |
| WASI | Componente WebAssembly | Entornos WASI y navegador |
El modo bin es probablemente la forma más sencilla de entender el cambio de fondo: una aplicación PHP compilada asà puede arrancar como ejecutable nativo, sin lanzar antes el binario php desde la lÃnea de comandos.
Eso no significa que el ecosistema PHP desaparezca del todo. Según el modo de compilación y la aplicación, los binarios pueden seguir dependiendo de PHPX, libphp y otras bibliotecas configuradas durante la compilación.
TypePHP tampoco elimina Zend en todos los escenarios. Las funciones dinámicas, las funciones internas, ciertos objetos, la reflexión y otros componentes pueden interoperar con Zend a través de PHPX, la capa que usa el proyecto para conectar ambos mundos.
La diferencia es que las funciones de usuario compiladas por TypePHP ya no necesitan ejecutarse como una secuencia de opcodes de Zend. El enfoque recuerda en parte al que sigue FFI en PHP para llamar a funciones C, aunque aquà la interoperabilidad va en el sentido contrario: es TypePHP quien expone código PHP compilado al mundo nativo.
Un compilador de PHP escrito en PHP
Hay otro detalle técnico curioso: TypePHP está escrito enteramente en PHP.
El compilador tpc puede compilar su propio código fuente usando TypePHP. A esto se le llama compilador autoalojado (self-hosting), y es más que una curiosidad: que un compilador sea capaz de compilarse a sà mismo es un hito arquitectónico importante, porque exige que el lenguaje soportado sea capaz de implementar algo tan complejo como el propio compilador.
El proyecto asegura que no depende de código pegamento en C o C++ para implementar el compilador. C++ aparece solo como lenguaje intermedio generado durante la compilación.
Un proyecto básico puede instalar TypePHP vÃa Composer:
composer require --dev swoole/typephp
Y compilarse con:
vendor/bin/tpc.php project.yml
También se puede clonar el repositorio y ejecutarlo directamente:
git clone https://github.com/swoole/typephp.git
cd typephp
composer install
php bin/tpc.php --help
En Linux, el entorno de compilación exige PHP 8.4 u 8.5, un compilador compatible con C++17, CMake 3.24 o superior, Composer 2 y varias bibliotecas adicionales según las funciones que se usen.
En Debian y Ubuntu, las dependencias básicas que lista el proyecto se instalan con:
sudo apt install build-essential cmake pkg-config libgmp-dev libmpfr-dev
En Fedora, RHEL y derivados:
sudo dnf install gcc gcc-c++ cmake pkgconf-pkg-config gmp-devel mpfr-devel
Y en Arch Linux:
sudo pacman -S base-devel cmake pkgconf gmp mpfr
Linux x86-64 es hoy la plataforma principal de desarrollo y la única con CI completo, aunque TypePHP también ofrece objetivos para Linux ARM64, macOS ARM64, Windows x64 y WASI.
Dónde intenta ganar rendimiento: los tipos nativos
La compilación AOT por sà sola no explica toda la propuesta de rendimiento de TypePHP. Una parte importante del proyecto es su modelo de tipos.
PHP mantiene tradicionalmente bastante flexibilidad en tiempo de ejecución. Esa flexibilidad viene de perlas para desarrollar, pero tiene un coste cuando entran en juego millones de operaciones matemáticas o accesos a estructuras de datos.
TypePHP permite activar:
use native_types;
A partir de ahÃ, ciertos tipos de PHP pueden usar una representación nativa mucho más directa. Por ejemplo:
| Tipo TypePHP | Representación C++ aproximada |
|---|---|
int | int64_t |
float | double |
bool | bool |
Una función tan simple como esta
<?php
use native_types;
function fib(int $n): int
{
if ($n == 1 || $n == 2) {
return 1;
}
return fib($n - 1) + fib($n - 2);
}
se traduce asà en operaciones numéricas nativas, en lugar de pasar cada cálculo por las estructuras dinámicas habituales de Zend.
El proyecto ofrece además tipos numéricos de alta precisión como bigInt, decimal y bigFloat, apoyados en GMP, libmpdec y MPFR respectivamente.
Los contenedores tipados son otra pieza del enfoque. Incluyen:
std::array
std::vector
std::map
std::ordered_map
Por ejemplo:
<?php
use native_types;
function main(): void
{
$vector = std::vector(Type::Int);
$vector[] = 10;
$vector[] = 20;
$vector[] = 30;
$sum = 0;
foreach ($vector as $value) {
$sum += $value;
}
echo $sum . "n";
}
La ventaja potencial pesa más cuanto mayor es el volumen de datos que procesa el algoritmo.
Un benchmark publicado por el propio proyecto compara una carga intensiva de actualización de elementos usando arrays de PHP, el std::array de TypePHP y el std::vector de C++.
| Implementación | Tiempo publicado |
|---|---|
| Array PHP con JIT | 67,6 segundos |
std::array con TypePHP AOT | 6,4 segundos |
std::vector en C++ | 6,2 segundos |
En esta prueba concreta, TypePHP fue unas diez veces más rápido que el array PHP y se quedó muy cerca del resultado de C++.
Ese dato hay que leerlo con cuidado: es un benchmark publicado por el propio proyecto y usa una carga especialmente favorable a la compilación estática y las estructuras tipadas. No significa que una aplicación WordPress, Laravel o Symfony vaya a correr diez veces más rápido de golpe solo por usar TypePHP.
La documentación publica también resultados con bench.php y micro_bench.php, dos benchmarks incluidos en el propio árbol de fuentes de PHP:
| Benchmark | PHP interpretado | TypePHP AOT -O3 | Diferencia |
|---|---|---|---|
bench.php | 5,034 s | 0,603 s | ~8× |
micro_bench.php | 13,045 s | 2,021 s | ~6,5× |
De nuevo, son medidas del proyecto, no garantÃas de rendimiento para cualquier aplicación.
Para una aplicación web que se pasa la mayor parte del tiempo esperando consultas SQL, Redis, almacenamiento, APIs externas u otros servicios remotos, acelerar las operaciones aritméticas puede traducirse en una mejora global mucho más discreta.
TypePHP resulta conceptualmente más atractivo para cargas intensivas de CPU: procesamiento masivo de datos, cálculo numérico, procesos por lotes, parsers, generación de informes o ciertos servicios de larga duración.
TypePHP frente a PHP, OPcache y JIT
Conviene no tratar estas tecnologÃas como sustitutas directas entre sÃ.
| TecnologÃa | Cuándo compila | Salida | ¿Necesita Zend en runtime? |
|---|---|---|---|
| PHP tradicional | En ejecución | Opcodes | Sà |
| OPcache | Guarda el bytecode compilado | Opcodes en caché | Sà |
| PHP JIT | Durante la ejecución | Código máquina en rutas seleccionadas | Sà |
| TypePHP | Antes de la ejecución | Código nativo | Parcialmente, según qué funciones se usen |
OPcache sigue teniendo todo el sentido para aplicaciones PHP convencionales, y el JIT también puede ayudar en ciertas cargas sin necesidad de meter un proceso de compilación AOT adicional.
TypePHP persigue otra cosa: que partes de un proyecto de software se diseñen desde el principio como código PHP compilado estáticamente.
Esto puede resultar especialmente interesante para extensiones. En lugar de escribir una extensión PHP entera en C, TypePHP puede compilar código como extensión cargable:
bin/tpc.php extension/ -m ext -o my_extension
También puede producir una biblioteca compartida:
bin/tpc.php lib/ -m lib -o mylib
La posibilidad de combinar PHP y C++ lleva este modelo un poco más lejos: TypePHP puede declarar funciones implementadas en C++ mediante ficheros .stub.php y luego llamarlas desde código PHP compilado. Es una opción intermedia entre escribir toda una aplicación en PHP y mover a mano las secciones crÃticas de rendimiento a una extensión en C.
La gran limitación: TypePHP todavÃa no es "todo PHP"
Esta es la parte que se pierde fácilmente si solo se miran los benchmarks.
TypePHP no promete compatibilidad total con PHP. El proyecto reconoce abiertamente que implementa un subconjunto del lenguaje, delimitado y probado. Algunas restricciones son necesarias para que la compilación AOT sea posible.
Por ejemplo, el ámbito global es solo de declaración, con el código ejecutable metido dentro de funciones o métodos. El modo binario exige también una función main(). Un programa mÃnimo se ve asÃ:
<?php
function main(): void
{
echo "Hello World!n";
}
Se compila y se ejecuta con:
bin/tpc.php hello.php
./hello
Algunas construcciones muy dinámicas, con referencias, reflexión, clausuras o ciertas declaraciones, pueden no estar todavÃa soportadas. El proyecto mantiene documentación especÃfica sobre las caracterÃsticas incompatibles, que cualquier equipo deberÃa revisar antes de plantearse adoptarlo.
Esto hace que TypePHP sea mucho más fácil de evaluar para código nuevo o módulos con mucha carga de cálculo que como sustituto inmediato de una aplicación PHP grande ya existente.
SerÃa prematuro dar por hecho que hoy se puede compilar sin tocar nada una aplicación WordPress, Magento, Drupal, Laravel o Symfony entera. El uso intensivo de comportamiento dinámico, reflexión, clases generadas, paquetes y extensiones que tienen estos ecosistemas obliga a evaluar la compatibilidad caso por caso.
Hay implicaciones también para quien administra sistemas. El despliegue puede dejar de ser simplemente:
PHP + aplicación
y pasar a depender del modo elegido:
binario + PHPX + libphp + bibliotecas nativas
La compatibilidad entre la versión de PHP, las cabeceras, php-config, libphp, ZTS o NTS y las extensiones instaladas pasa entonces a importar de verdad. La propia documentación del proyecto avisa de problemas de ABI cuando se mezclan componentes compilados contra distintas versiones o configuraciones de PHP.
¿Protege TypePHP el código fuente?
El proyecto plantea otra ventaja potencial: distribuir un binario compilado en vez de los ficheros PHP originales. Eso dificulta bastante recuperar el código fuente, aunque decir que un binario no se puede descompilar serÃa ir demasiado lejos.
Los binarios nativos se pueden seguir examinando con herramientas de ingenierÃa inversa, desensambladores y descompiladores. Lo que desaparece es la posibilidad de abrir sin más un fichero .php y leer el código original.
Puede resultar útil para ciertos productos comerciales, appliances o software distribuido a clientes, aunque la seguridad de un producto nunca deberÃa depender solo de ocultar su implementación.
Un paso más en la evolución del rendimiento de PHP
TypePHP llega después de varios cambios importantes en cómo ejecuta código PHP. OPcache redujo el coste de compilar scripts una y otra vez, PHP 7 rehÃzo buena parte del Zend Engine y mejoró el rendimiento general, PHP 8 metió el JIT, y las versiones siguientes han seguido puliendo lenguaje, sistema de tipos y motor.
TypePHP propone ahora un camino distinto: que PHP pueda salirse en parte de su modelo de ejecución tradicional y convertirse en software compilado antes del despliegue.
Aún es pronto para saber cuánto espacio va a encontrar este enfoque dentro del ecosistema PHP. Su éxito no dependerá solo de benchmarks vistosos: el proyecto necesitará demostrar estabilidad, compatibilidad, herramientas de depuración, integraciones, mantenimiento a largo plazo y una experiencia de compilación lo bastante sencilla como para justificar meter una fase más en el proceso.
Pero la idea tiene una consecuencia interesante: PHP podrÃa usarse para construir componentes que antes se habrÃan reescrito en C++, Rust o Go solo por rendimiento. Eso no significa que TypePHP vaya a sustituir esos lenguajes. Significa que, para algunas cargas, reescribir en otro lenguaje el PHP crÃtico en rendimiento puede dejar de ser la única opción cuando el cuello de botella está en la CPU.
Preguntas frecuentes
¿Qué es TypePHP?
TypePHP es un compilador AOT desarrollado por el equipo de Swoole que transforma código PHP en C++17 y luego en código máquina nativo. Puede generar ejecutables, extensiones PHP, bibliotecas compartidas y ciertos objetivos WebAssembly.
¿Sustituye TypePHP a OPcache o al JIT de PHP?
No necesariamente. OPcache y el JIT actúan dentro del modelo de ejecución tradicional de PHP, mientras que TypePHP compila el código antes de ejecutarlo. Son enfoques distintos, útiles para tipos de carga distintos.
¿Puede TypePHP compilar una aplicación entera de Laravel o WordPress?
No conviene darlo por hecho. TypePHP soporta hoy un subconjunto definido de PHP y mantiene una lista de caracterÃsticas incompatibles. Los frameworks y CMS que dependen mucho de comportamiento dinámico necesitan probarse y evaluarse caso por caso.
¿Es TypePHP diez veces más rápido que PHP?
No en general. El proyecto ha publicado un benchmark concreto en el que uno de sus contenedores tipados fue unas diez veces más rápido que un array PHP con JIT, junto con benchmarks de lenguaje que muestran mejoras de entre 6,5 y 8 veces. El resultado real depende del código, la CPU, el compilador, la configuración y la carga de trabajo.
Fuentes: documentación oficial de TypePHP AOT (Swoole) y repositorio oficial swoole/typephp en GitHub, con su documentación técnica, requisitos, benchmarks y modelo de compatibilidad. Fuente adicional: administraciondesistemas.com.
