はじめに
以前このような記事を投稿しました
PHP7.4の新機能、FFIでGoを使ってみた
https://qiita.com/i4M1k0SU/items/7c0db12e047e0fbf7550
この記事ではPHP7.4での新機能、FFIからGoで実装した共有ライブラリを利用し、FFIを利用しない場合と比べ20倍以上ものパフォーマンスを出すことができました
今回はPHP8.0に追加された新機能、 JITコンパイラ
を利用し、この結果にどこまで追いつけるかを検証します
PHP8.0の導入
PHP8.0はこの記事を投稿した段階ではまだ正式なリリースがされていません
今回はmacを利用しているのですが、DockerやVMは使わずhomebrewからネイティブ環境に導入することにしました
brew update
brew tap shivammathur/php
brew install shivammathur/php/php@8.0
brew link --overwrite --force php@8.0
JITコンパイラの有効化
php.iniを書き換えます
設定値の詳細については他の方の記事をご参照ください
調整次第でパフォーマンスに変化があるのかもしれませんが、今回の記事は以下の値を利用します
opcache.enable=1
opcache.enable_cli=1
# 以下は追記する必要があります
opcache.jit=1235
opcache.jit_buffer_size=128M
JITコンパイラでPHPはどれだけ速くなるか
以前書いた記事と全く同じ検証用コードです
フィボナッチ数列を40番目まで求めます
再帰を使っていて数が大きくなるほど計算に時間がかかるサンプルです
また、ついでにPHP8.0+FFIも検証します
const COUNT = 40;
$ffi = FFI::cdef(
'extern unsigned int calcFibonacci(unsigned int p0);',
'[PATH]/fibonacci.dylib'
);
// 比較対象のPHP実装サンプル
function calcFibonacci(int $i): int {
if ($i < 2) {
return $i;
}
return calcFibonacci($i - 1) + calcFibonacci($i - 2);
}
// Go(FFI)実装の実行速度計測
$startTime = microtime(true);
for($i = 1; $i <= COUNT; $i++) {
$ffi->calcFibonacci($i);
}
$time = microtime(true) - $startTime;
echo "Go(FFI): {$time} 秒\n";
// PHP実装の実行速度計測
$startTime = microtime(true);
for($i = 1; $i <= COUNT; $i++) {
calcFibonacci($i);
}
$time = microtime(true) - $startTime;
echo "PHP: {$time} 秒\n";
結果
小数第三位を四捨五入しています
FFI 利用 | PHP のみ | |
---|---|---|
PHP7.4 (前回の結果) | 1.58 秒 | 33.62 秒 |
PHP8.0 without JIT (and opcache) | 1.86 秒 | 42.44 秒 |
PHP8.0 with JIT | 1.96 秒 | 9.50 秒 |
良い結果が出たのではないでしょうか
気になる点として、PHP8.0は何もしなくてもPHP7.4より速くなると言った内容の記事もありましたが、私の環境ではJITコンパイラ無効時はPHP7.4より遅くなっているようです
また、FFI利用時は誤差レベルかもしれませんがJITコンパイラの設定に関係なく、少し遅くなっているようです
とは言ってもJITコンパイラを有効にした場合の結果はとても優秀で、FFIに追いつきこそはしませんが、かなり大きな速度向上が見込めるのではないでしょうか
また、FFIとは異なり、PHP以外の言語で実装する必要なく、そのまま高速化できる点も大きなメリットではないでしょうか
設定を有効にするだけでここまでの高速化が可能なので、積極的に利用していきたい機能です