8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PHP8】JIT=on の Docker を作ってみた。触ってみたら爆速だったよ。

Last updated at Posted at 2019-07-05

PHP8 で JIT が使えるようになるそうなので、ワクワクが止まりません。手軽に触れるイメージが Docker ないものか。

TL; DR

PHP のソースコードの masterからコンパイルして JIT を有効にした Docker イメージを作ってみました。Mac に標準インストールされている PHP7.1 と比較して 2〜5 倍近く速いです。

信じられないかもしれませんが、macOS に標準インストールされている PHP v7.3.11 をローカルで動かすより、ラズパイ3 の Docker 上で動かした方が JIT が有効になっていなくても速いんです。(詳しくは TS; DR)

🐒   2021/03/21 追記: 公式の PHP8 の Docker イメージもラズパイ(ARM 系 CPU)でも動くようになりました。しかし、当イメージおよび公式も、残念ながらラズパイ上では JIT を有効にできません。ARM 系 CPU 用の JIT の PHP モジュールがまだ完成していないためです。それでも PHP 7 系より速いですが。

docker pull keinos/php8-jit:latest


Docker Pulls

  • このイメージは、Mac や Windows の Intel/AMD の x86_64 系以外にも、ラズパイ3、ラズパイZero の Docker でも動くようにしています。

    • 動作確認 OS とハード:
      • macOS Mojave (MacBookPro Early 2015, x86_64)
      • Raspbian Stretch (RaspberryPi 3, ARMv7l)
      • Raspbian Buster (RaspberryPi ZeroW, ARMv6l)
      • いずれも Docker v19.03.2
  • このイメージは、JIT を有効にしていますが、ARM 系 CPU の場合、無効になってしまいます。

  • このイメージは、mbstring を有効、languagejapanese、タイムゾーンを Asia/Tokyo に設定してあります。

  • Docker イメージ: https://hub.docker.com/r/keinos/php8-jit @ Docker Hub

  • Dockerfile: https://github.com/KEINOS/Dockerfile-of-PHP8-JIT @ GitHub

  • 拡張モジュール:

  • PHP Info:

  • Reference:

簡易速度テスト

Test v5.6.40 v7.0.33 v7.1.33 v7.2.31 v7.3.18 v7.4.6 8.0.0-dev
(JIT Off)
8.0.0-dev
(JIT On)
Fibonacci(32) 1.521 0.665 0.598 0.269 0.239 0.194 0.261 0.107
Zundoko-Kiyoshi Looping 2.485 1.462 1.413 0.701 0.646 0.636 0.672 0.416
-- Zend Bench --
simple 0.178 0.100 0.101 0.064 0.051 0.041 0.054 0.002
simplecall 0.186 0.027 0.027 0.010 0.010 0.007 0.010 0.001
simpleucall 0.210 0.071 0.080 0.023 0.018 0.025 0.022 0.001
simpleudcall 0.226 0.076 0.088 0.028 0.021 0.021 0.024 0.001
mandel 0.491 0.320 0.329 0.189 0.190 0.175 0.189 0.007
mandel2 0.643 0.360 0.358 0.167 0.167 0.184 0.170 0.008
ackermann(7) 0.187 0.061 0.067 0.032 0.031 0.031 0.033 0.015
ary(50000) 0.031 0.008 0.007 0.007 0.008 0.007 0.007 0.007
ary2(50000) 0.025 0.006 0.005 0.006 0.007 0.006 0.006 0.006
ary3(2000) 0.298 0.142 0.124 0.059 0.047 0.044 0.049 0.015
fibo(30) 0.594 0.230 0.228 0.106 0.091 0.081 0.093 0.042
hash1(50000) 0.049 0.024 0.024 0.016 0.015 0.015 0.015 0.016
hash2(500) 0.053 0.022 0.023 0.013 0.008 0.008 0.008 0.011
heapsort(20000) 0.145 0.073 0.069 0.037 0.036 0.036 0.037 0.014
matrix(20) 0.130 0.067 0.062 0.034 0.035 0.030 0.030 0.014
nestedloop(12) 0.301 0.145 0.143 0.088 0.091 0.072 0.091 0.013
sieve(30) 0.151 0.041 0.053 0.021 0.018 0.014 0.017 0.005
strcat(200000) 0.027 0.014 0.015 0.011 0.011 0.011 0.010 0.010
--------------- ------- ------- ------- ------- ------- ------ ----- -----
Total 3.923 1.787 1.804 0.911 0.855 0.805 0.867 0.187

使い方

`docker run --rm -it keinos/php8-jit:latest`

基本構文

docker run --rm -it keinos/php8-jit:latest [コマンド] [引数]
コマンド実行例
docker run --rm -it keinos/php8-jit:latest php -a
  • docker run で「コンテナの起動」
  • --rm で「終了後にコンテナを破棄(remove)」(ロングオプションなので -- です)
  • -it でシェル操作をコンテナとつなげる。
    • -i -t もしくはロングオプションの --interactive --tty と同じ意味です。つまり、コンテナの標準入出力とローカルの標準入出力を tty 経由でつなげ、コンテナのシェル操作をローカルのシェルから行えるようになります。これを忘れると、実行コマンド終了後に入力待ちにならず処理が終わりコンテナがシャットダウンしてしまいます。
  • keinos/php8-jit:latest で「コンテナの元となるイメージを指定」
  • php でランタイムを指定
  • -a

対話モードで実行

PHP対話モードで実行
$ # コマンドや引数の指定がない場合は対話モードで起動します(デフォルトの動作)
$ docker run --rm -it keinos/php8-jit:latest
Interactive shell

php > echo phpversion();
8.0.0-dev
php > exit
$
$ # コマンドが php -a の場合と同じ動作です。
$ docker run --rm -it keinos/php8-jit:latest php -a
Interactive shell

php > echo phpversion();
8.0.0-dev
php > exit
$

PHP コマンドの直接実行

PHPコマンドを直接実行
$ # php --version の実行
$ docker run --rm -it keinos/php8-jit:latest php --version
PHP 8.0.0-dev (cli) (built: Jul 19 2019 07:09:36) ( 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
$
$ # php -r で `echo "hoge", PHP_EOL;` のスクリプトを実行
$ docker run --rm -it keinos/php8-jit:latest php -r 'echo "hoge", PHP_EOL;'
hoge
$

コンテナ内から PHP を実行

コンテナ内のシェルから実行
$ # /bin/sh でコンテナ内の Bourne Shell(sh)シェルを起動
$ docker run --rm -it keinos/php8-jit:latest /bin/sh
/ $ # コンテナ内の sh シェルから php -v を実行
/ $ php -v
PHP 8.0.0-dev (cli) (built: Jul 19 2019 07:09:36) ( 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
/ $ 
/ $ # コンテナ内の sh シェルから`echo "hoge", PHP_EOL;` のスクリプトを php -r で実行
/ $ php -r 'echo "hoge", PHP_EOL;'
hoge
/ $ # シェルを抜けてコンテナを終了
/ $ exit
$

コンテナにファイルをマウントして実行

ファイルをマウントして実行
$ # ローカルのファイルを用意
$ ls
test.php
$ cat test.php
<?php

echo 'Hello World!', PHP_EOL;

$ # test.php をマウントして実行
$ docker run --rm \
>   -v $(pwd)/test.php:/app/test.php \
>   keinos/php8-jit:latest \
>   php /app/test.php
Hello World!
$

コンテナにディレクトリをマウントして実行

ディレクトリをマウントして実行
$ # ローカルのディレクトリを確認
$ ls
src
$ ls src
index.php     functions.inc.php
$ # src ディレクトリをマウントして実行
$ docker run --rm \
>   -v $(pwd)/src:/app \
>   -w /app \
>   keinos/php8-jit:latest \
>   php index.php
Hello World! from a function.
$

ビルド

Docker Hub から Pull せずにイメージをビルドしたい場合は、リポジトリを clone してビルドしてください。

$ # 適当な作業ディレクトリに移動
$ cd ~/
$ # リポジトリを clone
$ git clone https://github.com/KEINOS/Dockerfile-of-PHP8-JIT.git php8
$ # リポジトリに移動
$ cd $_
$ # Docker イメージのビルド
$ docker build --no-cache -t php8-jit .
...

TS;DR(リリースまで JIT 我慢できない)

上記の Qiita 記事を読んでワクワクが止まらず、触ってみたい欲にかられました。

非公式ながらも PHP 8.0.0 Dev 版の Docker イメージはあるのですが、残念ながらデフォルトで JIT が有効になっておらず、mb_string なども一緒にコンパイルされていません。

また、PHP 8.0.0 とは言っても最新の master ブランチを使っているので一番 PHP8 に近いバージョンというだけのようですが、それでも一応 master は PHP8 用として進められているようです。

JIT の正式採用は PHP8 からと決定されたので、この Docker イメージは「いちはやく JIT の挙動をみるための目的で作成された」とのこと。どうやら JIT を有効にした場合に PHP のコンパイルに難があるようで、それらの注意点をまとめた記事をベースに作られたそうです。

測定

そこで、上記記事を参考に JIT および mb_string を有効にした PHP8 の Dockerfile を作ってみたので、測定してみました。自分でコンパイルしてみたいかたは、リポジトリclone して、docker build してみてください。

測定は「フィボナッチ数」の算出と「ズンドコキヨシ」ループです。リポジトリには Zend の ベンチマークも置いてあります。

テストコード

比較用スクリプト

実行結果

  • 同じ PHP8 同士でも JIT を有効にするだけで 2〜3 倍近く速なった。
  • Docker で PHP を使うなら 7.3.6 がバランス的(速度・安定的に)にベストと思われる。
PHPバージョン 実行環境 実測値(フィボナッチ数) 
PHP 5.6.40 Docker 1.4402780532837
PHP 7.1.23 ローカル実行 0.3146538734436
PHP 7.1.23 Docker 0.57761478424072
PHP 7.3.6 Docker 0.23189496994019
PHP 8.0.0-dev Docker
(JIT=off)
0.24225091934204
PHP 8.0.0-dev Docker
(JIT=on)
0.093664884567261

| PHPバージョン | 実行環境 | 実測値(ズンドコキヨシ) |
| :--- | :--: |:--- | :--- |
| php 5.6.40 | Docker | 2.3430778980255 |
| PHP 7.1.23 | ローカル実行 | 0.75591492652893 |
| php 7.1.23 | Docker | 1.3070819377899 |
| php 7.3.6 | Docker | 0.60567092895508 |
| php 8.0.0-dev | Docker
(JIT=off)| 0.6335301399231 |
| php 8.0.0-dev | Docker
(JIT=on)| 0.39926886558533 |

  • 検証結果
    • macOS のデフォルト PHP 7.1.23 のローカル実行と比較しても 2〜3 倍速い。
    • JIT を有効にしない場合は PHP8 on Docker がローカル実行の PHP7.1.23 よりやや速いくらい。
    • v7.1.23 と v7.3.6 では、v7.3.6 の方がローカルより速い。
  • 検証環境
    • マシン: MacBook Pro, 2.7 GHz IntelCore, 13inch Early 2015
    • OS: macOS Mojave (OSX 10.14.5)
    • Docker: 19.03.2
8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?