¿Cómo funciona el motor de Zend?: opcodes y op arrays

* fuente: George Schlossnagle, Advanced PHP Programming

Resumiendo, el motor de Zend compila, transforma,  el código del script en un código intermedio, más o menos, independiente de la máquina. Este código intermedio es una matriz ordenada (op array – de operations array-) de instrucciones conocidas como opcodes (operation code). Estos opcodes básicamente son tres direcciones de memoria: 2 operandos para las entradas, un tercer operando para la salida más el operador que procesa los operandos . Los operandos son todos constantes (representando valores estaticos) o un offset a una variable temporal (registro de la máquina virtual de Zend).

En el caso mas simple un opcode representa la operación sobre dos valores y su almacenamiento en un registro. En casos más complejos, los opcodes implementa flujos de control, reseteos de posiciones en el op array , bucles o codicionales.

Una representación del código intermedio:

– se asigna el registro 0 como un puntero a la variable $hi.
– se asigna el valor hello al registro 0
– reasigna el valo de $hi en el registro 2
– envía el registro 2 al buffer de salida.
– marca el valor de retorno del script en 1

Una vez creado el código intermedio se recorre el op array ejecutando un campo cada vez (ejecución);

Ambas fases, compliación y ejecución, son manejadas por dos funciones diferentes en en motor de Zend:

  • zend_compile
  • zend_execute

que internamente están definidas como punteros a funciones, lo cual significa que se puede crear una extensión que sobrescriba  cualquiera de estos campos y los substituya por por otras funciones propias en tiempo de ejecución.

Un aspecto importante de PHP es que todos los includes y requires suceden en tiempo de ejecución. Así cuando un script es compilado, el op array generado las funciones y clases definidas en el código son insertadas en la tabla de símbolos, pero los scripts incluidos no son compilados todavía.  Cuando el scritp es ejecutado, si se ha incluido algún elemento externo, es compilada y ejecutada en el momento.

Ojo : esto tiene repercusiones importantes:

Flexibilidad: PHP es un lenguaje de programación interpretado y por tanto permite inclusiones condicionales de funciones y clases

   if($condition) {
      include(“file1.inc”);
   }else {
     include(“file2.inc”);
  }

Velocidad: El tener que compilar sobre la marcha significa que una porción significativa de tiempo de ejecución de un script se gasta simplemente compilar sus dependencias. Si un archivo se incluye dos veces, debe ser analizado y ejecutado dos veces. include_once y require_once parcialmente resuelven ese problema, pero no lo resuelve del todo …… continua en las variables en PHP

Posted in php