Running php 8 with jit in docker in 5 minutes

The winter is coming! And along with it, the release of php 8 is approaching. If you can't wait to test your code in beta version of php 8, and at the same time feel jit, then please, under cat.



TL: DR;



All examples can be downloaded from github and immediately run: github.com/xtrime-ru/php8-test



Training



First you need to install docker and docker-compose.



Now let's create an opcache.ini file that will enable opcache and JIT in our container.

; Extended PHP.ini file to enable JIT.
; ====================================
; Place this file under /usr/local/etc/php/conf.d/
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.jit_buffer_size=32M
opcache.jit=1235




Now you need to create a Dockerfile in your working folder.

The list of packages and extensions is provided as an example. You can delete these lines or specify the extensions you need. Also, some of the popular extensions are already included in the base image. So there is no need to include json, xml and many others.



FROM php:8.0-rc-cli

COPY opcache.ini /usr/local/etc/php/conf.d/

RUN apt-get update && apt-get upgrade -y \
    && apt-get install apt-utils -y \
#
#      
    && apt-get install git zip vim libzip-dev libgmp-dev libffi-dev libssl-dev -y \
#
#      
    && docker-php-ext-install -j$(nproc) sockets zip gmp pcntl bcmath ffi \
#
#      pecl  ,   php 8 pecl  ,    
#    && PHP_OPENSSL=yes pecl install ev \
#    && docker-php-ext-enable ev \
#
#      
    && docker-php-source delete \
    && apt-get autoremove --purge -y && apt-get autoclean -y && apt-get clean -y




The last file remains. This is docker-compose.yml, which makes it easy to manage containers during development.



version: '3.5'
services:
  php8-test:
    build: ./
    container_name: php8-test
    restart: unless-stopped
    volumes:
      - ./:/app
    working_dir: /app
    entrypoint: "php -S 0.0.0.0:8000"
    ports:
      - "127.0.0.1:8000:8000"
    logging:
      driver: "json-file"
      options:
        max-size: "1024k"
        max-file: "2"




Now you can run the container build and tests.



  1. Build the image: docker-compose build
  2. Run the container in the background: docker-compose up -d
  3. We connect to the container: docker exec -it php8-test / bin / bash
  4. The current folder on the container is synchronized with the project folder. The files can be edited on the local machine.
  5. Download the benchmark file: github.com/php/php-src/blob/master/Zend/bench.php
  6. Run the bench: php bench.php
  7. You can disable jit or opcache inside the container here: /usr/local/etc/php/conf.d/opcache.ini to see how performance changes
  8. In docker-compose.yml, you can change the `volumes` and` workdir` directives to link other directories to the container. You can also change the entrypoint to run another command when the container starts. For example `php artisan serve` for laravel.
  9. All files can also be viewed in the browser at http://127.0.0.1:8000/

    The entrypoint and ports directives are responsible for this.




Benchmark



Benchmark file from the official php repository: github.com/php/php-src/blob/master/Zend/bench.php



#########################
# php 7.4.9
# opcache.enable=1
# opcache.enable_cli=0

simple             0.053
simplecall         0.007
simpleucall        0.019
simpleudcall       0.022
mandel             0.182
mandel2            0.220
ackermann(7)       0.038
ary(50000)         0.006
ary2(50000)        0.005
ary3(2000)         0.045
fibo(30)           0.069
hash1(50000)       0.014
hash2(500)         0.008
heapsort(20000)    0.036
matrix(20)         0.034
nestedloop(12)     0.089
sieve(30)          0.014
strcat(200000)     0.006
------------------------
Total              0.867

#########################
# php 7.4.9
# opcache.enable=1
# opcache.enable_cli=1

simple             0.007
simplecall         0.003
simpleucall        0.004
simpleudcall       0.003
mandel             0.088
mandel2            0.113
ackermann(7)       0.036
ary(50000)         0.006
ary2(50000)        0.007
ary3(2000)         0.039
fibo(30)           0.055
hash1(50000)       0.012
hash2(500)         0.008
heapsort(20000)    0.030
matrix(20)         0.029
nestedloop(12)     0.041
sieve(30)          0.011
strcat(200000)     0.007
------------------------
Total              0.499

#########################
# php 8.0-rc
# opcache.enable=1
# opcache.enable_cli=1
# opcache.jit_buffer_size=128M
# opcache.jit=1235

simple             0.002
simplecall         0.001
simpleucall        0.001
simpleudcall       0.001
mandel             0.008
mandel2            0.009
ackermann(7)       0.016
ary(50000)         0.006
ary2(50000)        0.007
ary3(2000)         0.015
fibo(30)           0.030
hash1(50000)       0.016
hash2(500)         0.011
heapsort(20000)    0.014
matrix(20)         0.012
nestedloop(12)     0.010
sieve(30)          0.004
strcat(200000)     0.006
------------------------
Total              0.168




JIT, of course, greatly speeds up CPU-related operations. But something else struck me. Php defaults to opcache.enable_cli = 0. If you enable this option, you can get a two-fold increase in the benchmark. Personally, I did not know that opcache can speed up cli commands so much.



I have tested several times on clean containers, as well as pre-cleaning the opcache. The result is always the same: opcache.enable_cli = 1 speeds up the benchmark from the first run.



The opcache.enable documentation says: "If disabled, the code will not be optimized and cached."



Unfortunately, in real cli scripts, the results after enabling opcache.enable_cli and jit can be very different. On one project I got a gain of 5% (4.0 sec -> 3.8 sec), and on the other project, on the contrary, a slowdown (0.088 sec -> 0.11 sec). Therefore, you should definitely test the settings on your own projects.



All Articles