15 August

Запускаем php 8 с jit в docker за 5 минут

PHPServer optimization
Tutorial
Recovery mode
Зима близко! А вместе с ней близится и релиз php 8. Если вам не терпится протестировать свой код в beta версии php 8, а заодно пощупать jit, то прошу под кат.

TL:DR;


Все примеры можно скачать с github и сразу запустить: github.com/xtrime-ru/php8-test

Подготовка


Для начала потребуется поставить docker и docker-compose.

Теперь создадим opcache.ini файл, который включит opcache и JIT в нашем контейнере.
; 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


Теперь в рабочей папке нужно создать Dockerfile.
Список пакетов и расширений приведен для примера. Можно удалить эти строки или указать нужные именно вам расширения. Так же часть популярных расширений уже включена в базовый образ. Так что подключать json, xml и многие другие не требуется.

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


Остался последний файл. Это docker-compose.yml, который позволяет легко управлять контейнерами при разработке.

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"


Теперь можно запускать сборку контейнера и тесты.

  1. Собираем образ: docker-compose build
  2. Запускаем контейнер в фоне: docker-compose up -d
  3. Подключаемся к контейнеру: docker exec -it php8-test /bin/bash
  4. Текущая папка на контейнере синхронизирована с папкой проекта. Файлы можно редактировать на локальной машине.
  5. Скачиваем файл бенчмарка: github.com/php/php-src/blob/master/Zend/bench.php
  6. Запускаем бенч: php bench.php
  7. Можно отключить jit или opcache внутри контейнера тут: /usr/local/etc/php/conf.d/opcache.ini, что бы посмотреть, как изменится производительность
  8. В docker-compose.yml можно изменить директивы `volumes` и `workdir`, что бы залинковать другие директории в контейнер. Так же можно поменять entrypoint для запуска другой команды при старте контейнера. Например `php artisan serve` для laravel.
  9. Все файлы так же можно посмотреть в браузере по адресу http://127.0.0.1:8000/
    За это отвечают директивы entrypoint и ports.


Бенчмарк


Файл бенчмарка из оффициального репозитория php: 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, конечно, сильно ускоряет операции связанные с использованием CPU. Но меня поразило другое. В php по умолчанию используется opcache.enable_cli=0. Если включить эту опцию, то можно получить двухкратный рост в бенчмарке. Лично я не знал о том, что opcache может так ускорять cli команды.

Я проверял несколько раз на чистых контейнерах, а так же с предварительной очисткой opcache. Результат всегда один и тот же: opcache.enable_cli=1 ускоряет бенчмарк начиная с первого запуска.

В документации opcache.enable написано: «Если запрещено, код не будет оптимизироваться и кешироваться.».

К сожалению, в реальных cli скриптах результаты после включения opcache.enable_cli и jit могут сильно отличаться. На одном проекте я получил выигрыш в 5% (4.0 сек -> 3.8 сек), а на другом проекте наоборот — замедление (0.088 сек -> 0.11 сек). Поэтому нужно обязательно тестировать настройки именно на своих проектах.
Tags:phpphp 8jitdockeropcache
Hubs: PHP Server optimization
+8
4.5k 28
Comments 11
Popular right now
PHP-программист
from 50,000 to 100,000 ₽СупердоставкаRemote job
PHP developer
to 250,000 ₽РНКБ Банк (ПАО)МоскваRemote job
PHP-разработчик
from 40,000 to 60,000 ₽Dota2.ruRemote job
PHP разработчик
from 60,000 to 120,000 ₽EmsoftМоскваRemote job
Разработчик PHP Senior
from 150,000 to 200,000 ₽SoftlineСанкт-ПетербургRemote job
Top of the last 24 hours