Farshid Rezaei's Logo

Try out JIT compiler with PHP 8.0

Farshid Rezaei 7 months ago
0 2 0 4:55

You probably heard the news a few months ago that the JIT compiler will be added to PHP 8. If you haven’t heard, it is this poll. 90% of contributors who voted for PHP 8. Since PHP 7.0, we have been making changes to improve performance, and this is a new breakthrough. performance for PHP. This is a very big feature, it was started to develop 2 years ago, PHP 8.0 is at least more than 1 year to launch. In this article, let’s take a look at what it is and try to use it.

What is JIT

Maybe you do not know about JIT so first I will explain what it is. You probably already know that PHP is an interpreted language, meaning that your code doesn’t need to be compiled before it runs (just like C / C ++). Instead, the PHP engine will read your code and run it. In other words, you do not code to compile into machine code for the computer to run, but to code a script and give it to PHP to run.

PHP has a virtual machine called Zend VM. Why call it a virtual machine, because it acts like your computer in running the code, as explained above. It is responsible for reading and running your PHP code. But before that, your code will be read and translated by PHP into opcode, which is the language that Zend VM understands. Then Zend VM can run that opcode. This is an illustration for easy understanding.

So we need a compile step first and then an interpreter step. To save time, we have a so-called OPCache (Opcode Cache) that stores the results of the compile step so there’s no need to compile next time.

That’s how PHP works until now. So now let’s talk about the JIT compiler. Its name is already available from the compiler. Meaning we will compile the code into a machine code to run. JIT stands for “Just-In-Time”, meaning it takes time to compile instead of compile first and then run. When you need to run, then compile.

For PHP, the JIT compiler will compile opcode into machine code and run that code instead of giving it to the Zend VM for it to run. So we do not need an interpreter anymore and of course, the code runs faster already

 

What is the JIT for?

Since PHP 7.0, PHP’s performance issue has been more concerned than ever, thanks in part to the competition from Facebook’s HHVM (also using the JIT compiler). OPCache, data structures, everything is optimized little by little to achieve the highest performance. And then there was almost no more left to improve, which brought about a significant increase in performance.

In addition, the performance of PHP for a server language can already be considered quite good, no longer the slow PHP in the past. So it’s time to expand PHP’s capabilities a bit, to areas like data analysis, 3D / 2D rendering …

In the past, high performance code was often written as a C / C ++ extension instead of a PHP package. For example, phpredis is always 6–7 times faster than predis. If the PHP code is compiled instead of the interpret, we will get PHP packages with the same performance as the extensions written in C / C ++.

So JIT compiler was chosen because this is the most interesting and potential direction.

Give it a try

After the introduction, let’s try it now. Since there is no release for PHP 8.0 yet, I will have to compile from source code. PHP’s source code is here. Although version 7.4 is still in alpha, the master is already 8.0. First, download the source code

wget -O php.zip https://github.com/php/php-src/archive/master.zip unzip php.zip cd php-src-master

 

Then install dependencies. I use Ubuntu, if you use other distros then find the same package yourself.

apt-get install autoconf bison dpkg-dev file g++ gcc libc-dev make pkg-config re2c libxml2-dev libsqlite3-dev

 

Generate build files.

./buildconf;

Then run ./configureto set up the build. Select options to compile PHP. You can choose a location to install by adding --prefix=<install_dir> . By default it will install /usr/local/binso if you have already installed another PHP version then remember to set this up. PHP will be installed into the path <install_dir>/bin/php . Add the path for the config file with --with-config-file-path and --with-config-file-scan-dir if you want.

./configure --help

 

For example, I run ./configure as below:

./configure --prefix=/opt --with-config-file-path=/opt/php --with-config-file-scan-dir=/opt/php/conf.d

Build

make -j$(nproc)
make install

Then we check by execute php -v

PHP 8.0.0-dev (cli) (built: Jul 15 2019 02:22:59) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies with Zend OPcache v8.0.0-dev, Copyright (c), by Zend Technologies

JIT compiler is a part of OPCache extension, so enable it before using JIT. Add these lines into php.ini:

zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1

You should add these 2 lines too. Detail about config you can check here

opcache.jit_buffer_size=32M
opcache.jit=1235

Now try running a PHP file with option -dopcache.jit_debug=1 . You will see compiled assembly code. For example, I have a file like this.

<?php

$a = 0;

for ($i = 0; $i < 10000; $i++) {
    $a += $i;
}

echo $a;

It will be compiled into assembly code as below:

 
JIT$/php-src-master/hello.php: ; (/php-src-master/hello.php)
         sub $0x10, %rsp
         lea 0x50(%r14), %rdi
         cmp $0xa, 0x8(%rdi)
         jnz .L1
         mov (%rdi), %rdi
         cmp $0x0, 0x18(%rdi)
         jnz .L12
         add $0x8, %rdi
 .L1:
         test $0x1, 0x9(%rdi)
         jnz .L13
 .L2:
         mov $0x0, (%rdi)
         mov $0x4, 0x8(%rdi)
  ; ...

 

Now try benchmark to see if it is faster. In the source code of PHP, there is a Zend / bench.php file for you to test. In this file are very much calculated code (hash, loop .etc). This is the result I ran out (reformatted for easy comparison).

 

Of course it runs faster, it’s not strange at all. I will try to benchmark another web app. I created a brand new Laravel project and benchmarked with the ApacheBench tool

ab -t10 -c10 http://test.localhost/

Got the same result

PHP 7.3: 131.37 req/s
PHP 8.0 + JIT: 133.57 req/s


TL;DR

In short, PHP is significantly faster, but for the time being, most of the existing PHP code in the world will not be much faster. However, new developments will soon open with PHP.

 

Source

Comments

Submit Comment