When compiling using bin/compile.php, you can also specify an "output file" with -o (this defaults to the input file, with .php removed). This will generate an executable binary on your system, ready to execute

Linting Code

If you pass the -l parameter, it will not execute the code, but instead just perform the compilation. This will allow you to test to see if the code even will compile (hint: most currently will not).

Debugging

Sometimes, you want to see what's going on. If you do, try the bin/print.php entrypoint. It will output two types of information. The first is the Control Flow Graph, and the second is the compiled opcodes.

Future Work

Right now, this only supports an EXTREMELY limited subset of PHP. There is no support for dynamic anything. Arrays aren't supported. Neither Object properties nor methods are supported. And the only builtin functions that are supported are var_dump and strlen.

But it's a start...

Debugging

Since this is bleeding edge, debuggability is key. To that vein, both bin/jit.php and bin/compile.php accept a -y flag which will output a pair of debugging files (they default to the prefix of the name of the script, but you can specify another prefix following the flag).

Performance

So, is this thing any fast? Well, let's look at the internal benchmarks. You can run them yourself with php bench.php, and it'll give you the following output (running 5 iterations of each test, and averaging the time):

Test Name

7.3 (s)

7.3.NO.OPCACHE (s)

7.4 (s)

7.4.NO.OPCACHE (s)

8.JIT (s)

8.NOJIT (s)

bin/jit.php (s)

bin/compile.php (s)

compiled time (s)

Ack(3,10)

1.1761

1.8715

1.1850

1.9010

0.6605

1.1573

0.4914

0.2830

0.2128

Ack(3,8)

0.0805

0.0991

0.0824

0.1096

0.0459

0.0791

0.2940

0.2817

0.0146

Ack(3,9)

0.3018

0.3616

0.3009

0.3709

0.1683

0.2931

0.3342

0.2818

0.0546

fibo(30)

0.0691

0.0837

0.0748

0.0890

0.0437

0.0684

0.2906

0.2808

0.0108

mandelbrot

0.0374

0.1298

0.0393

0.1493

0.0213

0.0374

0.3071

0.2969

0.0142

simple

0.0490

0.0729

0.0533

0.0758

0.0215

0.0581

0.3021

0.2864

0.0119

To run the benchmarks yourself, you need to pass a series of ENV vars for each PHP version you want to test. For example, the above chart is generated with::

Without opcache doing optimizations, the bin/jit.php is actually able to hang up with ack(3,9) and mandelbrot for 7.3 and 7.4. It's even able to hang with PHP 8's experimental JIT compiler for ack(3,9).

Most other tests are actually WAY slower with the bin/jit.php compiler. That's because the test itself is slower than the baseline time to parse and compile a file (about 0.12 seconds right now).

And note that this is running the compiler on top of PHP. At some point, the goal is to get the compiler to compile itself, hopefully cutting the time to compile down by at least a few hundred percent.

Simply look at the difference between everything and the "compiled time" column (which is the result of the AOT compiler generating a binary). This shows the potential in this compilation approach. If we can solve the overhead of parsing/compiling in PHP for the bin/jit.php examples, then man could this fly...