jueves, 18 de diciembre de 2008

Compilando en PHP

Aunque esto no sea novedad para algunos, en PHP también podemos "compilar" el código, gracias a una extensión de PEAR(PHP Extensión and Application Repository) llamada bcompiler; ¿el porqué coloco compilar entre comillas?: porque en realidad bcompiler no compila, sino que genera los "bytecodes" que php normalmente genera para ejecutar los scripts en memoria.

Para los que conocen JAVA sabemos que los bytecodes son un semi-lenguaje de máquina optimizado para una rápida lectura y ejecución por medio de las denominadas "Máquinas Virtuales" como lo es JAVA, y últimamente .NET Framework, entre otras.

En el manual sobre bcompiler (en inglés) se trata de la compresion del bytecode, y para configurarlo se requiere de muchas cosas que decidí omitir; lo que pasa es que el bytecode resultante del script puede ser incluso más del doble del tamaño (en bytes) que el archivo fuente original, ¿por qué?: simplemente porque en el bytecode se especifican muchos más datos, además del algoritmo en sí, de modo que la máquina virtual pueda traducirlo al lenguaje de máquina de la máquina (valga la redundancia) en donde se ésta ejecutando, como la mundialmente conocida arquitectura x86.

Instalación

Windows: En paquetes como WAMP y XAMMP (windows), ésta librería ya viene incluida, sólo basta instalar/configurar primero PEAR y luego incluir en el archivo de configuración php.ini la línea: extensión=php_bcompiler.dll en "dynamic extensions", PEAR no es realmente necesario, pero puede ser que necesiten de algunas funciones de PEAR.

GNU/Linux: aquí es otra Historia, pueden probar si el paquete XAMMP para linux trae la librería, pero no se los aseguro, además con PEAR lo puende instalar, de todos modos intente añadir al archivo de configuración php.ini: extensión=bcompiler.so y luego pruebe con phpinfo(); si la extensión bcompiler aparece (debe reiniciar apache).

Ubuntu 8 LTS: con el APACHE/PHP instalados por synaptic, instale los siguiente paquetes por
synaptic:

  • pear
  • php5-dev
  • bzip2
  • libbz2-1.0
  • libbz2-dev
  • libzip1
  • libzip1-dev
  • pbzip2
Una vez instalados abra el terminal (consola) y ejecute (le solicitará contraseña del administrador):

sudo pecl install bcompiler-0.8.tgz

Añada al archivo de configuración php.ini: extensión=bcompiler.so
Reinicie apache y compruebe que aparece la extensión bcompiler por phpinfo();

¡Manos a la Obra!

Para precompilar nuestro primer script necesitamos 3 archivos (origen.php, destino.php, compila.php); en origen.php estará el código fuente, a destino.php debe otorgarle PERMISOS DE ESCRITURA (GNU/Linux), y en compila.php coloque lo siguiente:

<?php
$fh = fopen("destino.php", "w");
bcompiler_write_header($fh);
bcompiler_write_file($fh, "origen.php");
bcompiler_write_footer($fh);
fclose($fh);
?>

Sólo basta ejecutar desde el explorador http://localhost/compila.php y si no aparecen errores está listo!: ejecute http://localhost/destino.php y aparecerá lo mismo que en origen.php, pero si revisa el código de destino.php notará que ya no es el mismo código, sino un conjunto de datos incomprensibles.

Puede incluso compilar todo tu sistema en php y puede utilizar ambos archivos: los bytecodes o los normales, bcompiler se encarga de todo, puede incluso hacer include y require a un archivo bytecode php de bcompiler, ambos pueden tener la extensión ".php".

Eso sí: se puede duplicar el tamaño en bytes del sistema, pero el rendimiento es el mismo: los no-compilados deben de interpretarse y luego compilarse en memoria antes de ser ejecutados; los precompilados "pesados" pasan a memoria inmediatamente, y si utiliza bytecodes comprimidos tienen que "descomprimirse" y ejecutarse. así que básicamente el rendimiento de su sistema no variará mucho.

El único detalle sería el comportamiento de __LINE__ y de los reportes de errores, como es una extensión experimiental puede ser que el valor retornado por éstas funciones no sea el mismo que cuando se ejecuta un script normal (no precompilado); por eso le recomiendo evaluar bien todo su código antes de precompilarlo.

2 comentarios:

JuanCarlos dijo...

hola, tu dices "bcompiler se encarga de todo, puede incluso hacer include y require a un archivo bytecode php de bcompiler" pero le puse y no compila los .php que son llamados, solo compila el especificado, lo ideal seria saber si hay una libreria desarrollada para detectar todos los .php en subdirectorios y a partir de ahi compilar todo la apicacion, si sabes de algo, chevere, sino, buscaré y en ultimo caso, desarrollare ese programa y te comentare por aca mismo.

salu2

Maycol Alvarez dijo...

lo que quise decir es que bcomplier tiene en cuenta los includes del archivos que pretendes compilar, para compilar todo el proyecto basta con crear una función recursiva que busque en todo el árbol, aunque actualmente xcache, eacelerator y otras realizan una compilación automática como la que quieres