PHPのJIT
A JIT compiler for PHPを読んだメモ
これまでのPHPの実行
PHPはスクリプト言語なので、機械語にcomplieはしない
Zend EngineがコードをパースしてASTにし、opcodeに変換する
opcodeはZend VMの実行単位
PHPのコードよりもlow-levelなので、PHPのコードよりは早く機械語に変換できる
しかし、機械語そのものではないのでcomplile言語よりは遅い
OPcacheによってopcodeをキャッシュする仕組みがある
2度目の実行移行はキャッシュしたopcodeを使う
JITでなんで早くなる?
PHP 8でJITがのると2016年にDmitry Stogovがpostした
2019年1月にRFCが出た https://wiki.php.net/rfc/jit
PHP 8より前
opcodeの出力を実行時に機械語にinterpreting
一度codeを実行したら、二度目移行はopcacheでcacheがきく
JIT
opcodeの出力を機械語にcompile
機械語のobject codeを実行する
JITはopcacheが利かない分不利に見える。実行時に毎回opcodeを機械語にcompileする無駄がある。これをどうする?本当に効果があるの?
...という検証を https://github.com/zendtech/php-src/tree/jit-dynasm/ext/opcache/jit でやったらしい
JITの場合も一度機械語にしたら次からはそれを利用できる場合もあるのでは?kadoyau.icon
何を・どのくらいの頻度で・どの粒度でコンパイルするかによってアプローチは異なる
JITのなかにはコードを一度だけcompileして、一度にオブジェクト全体になることもあれば、一度に1つのメソッドになるとかいろいろある(?)
すべての値はcompile時にデータ型をもって、実行時に値が取りうる範囲を制限する
JITはランタイムに実行されて内部で行われている処理を解析できるので、型推論よりも良い仕事ができる
ランタイムに行われるので、AOTよりもランタイムの情報を知っているということ
一方、JITの初回実行はinterpreterよりも遅い。stepがinterpreterよりも多いため
Q. で速度早くなるの?
A. 典型的なワークロードでは別に早くならない
As the mailinglist post notes, no real performance improvements were made at the time, at least for typical web workloads.
でもCPU intensiveな処理ではめっちゃ早くなるらしい
https://externals.io/message/102415
Zeev Suraskiの2018年のベンチマーク
https://www.youtube.com/watch?v=dWH65pmnsrI
kadoyau.icon
結局なぜJITで早くなるのかは理解できなかった
ベンチマークでは早くなっている。原理がよくわからない
https://kinsta.com/jp/blog/php-8/ 2021年08月31日
opcodeが低レベルの中間表現であっても、マシンコードにコンパイルする必要があります。JITは「IR(中間表現)の新し形を導入しません」が、DynASM(コード生成エンジン用の動的アセンブラ)を使用して、PHPバイトコードから直接にネイティブコードを生成します。
つまり、JITは中間コードの重要な部分をマシンコードに変換します。コンパイルをバイパスするおかげで、パフォーマンスとメモリ使用状況を大幅に改善させるでしょう。
RFCを見るとLLVMではなくDynAsmが優秀なのでそれがZend VMでの実行より早いということ?
【PHP8】PHPでJITが使えるようになる - Qiita(2020年01月15日に更新)
コメントに詳しい補足がある
#PHPの内部構造