PHP 8: JIT のセットアップ方法

in Vlog

(jp) =

PHP 8 では、JIT コンパイラが PHP のコアに追加され、パフォーマンスが劇的に向上する可能性があります。 実際の Web アプリケーションへの実際の影響については、補足説明がいくつかあります。そのため、JIT がどのように機能するかについていくつかのベンチマークを実行しました (関連するすべての参考文献も脚注にリストしました)。

話したいことがいくつかあるので、JIT のセットアップ方法についてもブログ投稿を捧げたいと思います。

正直なところ、JIT の設定は、私が今まで見た中で最も混乱を招く PHP 拡張機能の構成方法の 1 つです。 幸いなことに、より簡単にセットアップできるように、いくつかの構成の省略形が用意されています。 それでも、JIT 構成について詳しく知ることは良いことなので、ここに行きます。

まず第一に、JIT は opcache が有効になっている場合にのみ機能します。これはほとんどの PHP インストールのデフォルトですが、次のことを確認する必要があります。 opcache.enable は 1 に設定されていますphp.ini ファイル。 JIT 自体を有効にするには、次のように指定します。 opcache.jit_buffer_sizephp.ini.

コマンドライン経由で PHP を実行している場合は、これらのオプションを -d それらを追加する代わりに、フラグ php.ini:

php -dopcache.enable=1 -dopcache.jit_buffer_size=100M

このディレクティブが除外されている場合、デフォルト値は 0 に設定され、JIT は実行されません。 CLI スクリプトで JIT をテストする場合は、次を使用する必要があります。 opcache.enable_cli 代わりに opcache を有効にするには:

php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=100M

の違い opcache.enableopcache.enable_cli たとえば、組み込みの PHP サーバーを実行している場合は、最初のものを使用する必要があります。 実際に CLI スクリプトを実行している場合は、 opcache.enable_cli.

続行する前に、JIT が実際に機能することを確認し、ブラウザーまたは CLI (JIT をテストする場所によって異なります) からアクセスできる PHP スクリプトを作成し、次の出力を確認しましょう。 opcache_get_status():

var_dump(opcache_get_status()['jit']);

出力は次のようになります。

array:7 [
  "enabled" => true
  "on" => true
  "kind" => 5
  "opt_level" => 4
  "opt_flags" => 6
  "buffer_size" => 4080
  "buffer_free" => 0
]

もしも enabledon 本当です、あなたは行ってもいいです!

次に、JIT を構成する方法がいくつかあります (ここから構成の混乱に入ります)。 JIT をいつ実行するか、どれだけ最適化を試みるかなどを構成できます。これらのオプションはすべて、単一の (!) 構成エントリを使用して構成されます。 opcache.jit. 次のようになります。

opcache.enable=1 
opcache.jit=1255

では、その数字は何を意味するのでしょうか。 RFC には、それぞれの意味がリストされています。 注意: これはビット マスクではなく、各数値は別の構成オプションを表すだけです。 RFC には次のオプションがリストされています。

# O — 最適化レベル

0 JITしないでください
1 最小限の JIT (標準の VM ハンドラーを呼び出す)
2 選択的な VM ハンドラーのインライン化
3 個々の関数の静的型推論に基づく最適化された JIT
4 静的型推論とコール ツリーに基づいて最適化された JIT
5 静的型推論と内部手続き解析に基づく最適化された JIT

# T — JIT トリガー

0 最初のスクリプトの読み込み時にすべての関数を JIT する
1 最初の実行時の JIT 関数
2 最初のリクエストでプロファイリングし、2 番目のリクエストでホット関数をコンパイルする
3 オンザフライでプロファイリングし、ホットな関数をコンパイル
4 doc-comments で @jit タグを使用して関数をコンパイルする
5 JITのトレース

# R — レジスタ割り当て

0 レジスタ割り当てを行わない
1 ローカル ライナー スキャン レジスタ アロケータを使用する
2 グローバル ライナー スキャン レジスタ アロケータを使用する

# C — CPU 固有の最適化フラグ

0 なし
1 AVX 命令生成を有効にする

1 小さな 注意点: RFC ではこれらのオプションが逆順でリストされているため、最初の桁が C 値、秒 R、 等々。 単純に 4 つの構成エントリが追加されなかった理由は、私の理解を超えています。おそらく、JIT の構成を高速化するためです…そうですか?

tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください:

とにかく、内部が提案する 1255 最良のデフォルトとして、最大のジッティングを行い、トレース JIT を使用し、グローバル ライナー スキャン レジスタ アロケーターを使用し (それが何であれ)、AVX 命令生成を有効にします。

だからあなたのini設定(または -d flags) には次の値が必要です。

opcache.enable=1 
opcache.jit_buffer_size=100M
opcache.jit=1255

それを念頭に置いて opcache.jit ちなみにオプションです。 そのプロパティが省略されている場合、JIT はデフォルト値を使用します。

どのデフォルトですか? それは opcache.jit=tracing.

待ってください、それは先ほど見た奇妙なビットマスクのような構造ではありませんか? そうです: 元の RFC が通過した後、ビットマスクのようなオプションはユーザーフレンドリーではないことが内部で認識されたため、内部でビットマスクに変換される 2 つのエイリアスが追加されました。 あります opcache.jit=tracingopcache.jit=function.

この 2 つの違いは、関数 JIT は 1 つの関数のスコープ内のコードのみを最適化しようとするのに対し、トレース JIT はスタック トレース全体を調べてホット コードを特定して最適化できることです。 Internals では、トレース JIT を使用することをお勧めしています。これは、ほぼ常に最良の結果が得られるためです。 これらの結果については、私が行ったベンチマークで読むことができます。

したがって、最適な構成で JIT を有効にするために実際に設定する必要がある唯一のオプションは、 opcache.jit_buffer_size、しかし、明示的にしたい場合は、リストします opcache.jit それほど悪い考えではありません:

opcache.enable=1 
opcache.jit_buffer_size=100M
opcache.jit=tracing

//platform.twitter.com/widgets.js

関連記事

前の投稿
1月に植える6つの花
次の投稿
バーモント州のアイスフィッシングに最適な5つの湖