PHP8 で JIT が使えるようになるそうなので、ワクワクが止まりません。手軽に触れるイメージが Docker ないものか。
TL;DR
PHP8-ish(master
= 一番 PHP8 に近い状態)の PHP をソースからコンパイルして JIT を有効にした Docker イメージを作ってみました。Mac 以外にもラズパイ3、ラズパイZero の Docker で動くようにしています。
Mac に標準インストールされている PHP7.1 と比較して 2〜3 倍近く速いです。(詳しくは TS;DR)
docker pull keinos/php8-jit:latest
-
- 動作確認: macOS(x86_64), RaspberryPi 3(ARMv7l), RaspberryPi ZeroW(ARMv6l)(いずれも Docker v19.03.2)
- このイメージは、
JIT
を有効、mbstring
を有効、language
をjapanese
、タイムゾーンをAsia/Tokyo
に設定してあります。 - Image: https://hub.docker.com/r/keinos/php8-jit @ Docker Hub
- Source: https://github.com/KEINOS/Dockerfile-of-PHP8-JIT @ GitHub
- Extensions: ロードされているモジュール一覧
- PHP Info: phpinfo() の内容
- Reference:
- PHP GR8 | Musings, ninja ones @ Joe Watkins' Blog
- 下記記事とイメージが大変参考になりました。
- Compiling PHP 8 from source with JIT support @ arkadiuszkondas.com
- How to run PHP 8 with JIT support using Docker @ arkadiuszkondas.com
使い方
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
で対話モードで実行
$ # コマンドや引数の指定がない場合は対話モードで起動します(デフォルトの動作)
$ 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 --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 .
...
インストール済みの PHP モジュール
2019/10/04 現在コンパイル&インストール済みのモジュールは以下の通りです。追加して欲しいモジュールがあれば、リポジトリの Issues にあげてください。(日本語でおk)
$ docker run --rm -it keinos/php8-jit:latest php -m
[PHP Modules]
Core
ctype
curl
date
dom
FFI
fileinfo
filter
ftp
gd
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcntl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
soap
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
Zend OPcache
zlib
[Zend Modules]
Zend OPcache
TS;DR(リリースまで JIT 我慢できない)
- 【PHP8】PHPでJITが使えるようになる @ Qiita
上記の Qiita 記事を読んでワクワクが止まらず、触ってみたい欲にかられました。
非公式ながらも PHP 8.0.0 Dev 版の Docker イメージはあるのですが、残念ながらデフォルトで JIT が有効になっておらず、mb_string
なども一緒にコンパイルされていません。
また、PHP 8.0.0 とは言っても最新の master
ブランチを使っているので一番 PHP8 に近いバージョンというだけのようですが、それでも一応 master
は PHP8 用として進められているようです。
JIT の正式採用は PHP8 からと決定されたので、この Docker イメージは「いちはやく JIT の挙動をみるための目的で作成された」とのこと。どうやら JIT を有効にした場合に PHP のコンパイルに難があるようで、それらの注意点をまとめた記事をベースに作られたそうです。
- Compiling PHP 8 from source with JIT support @ Arkadius Zkondas' Blog
測定
そこで、上記記事を参考に 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