Contents
JIT がどのように動作するか(概要)
JIT は PHP スクリプトが OPcache によりバイトコード化された後、「ホット」 と判定された関数やループを検出し、実行中に CPU の命令セット向けに機械語へ再コンパイルします。このネイティブコードはメモリ上にキャッシュされ、次回以降の呼び出しではインタプリタをバイパスして直接実行されます。
- ハイブリッド方式:PHP 8 からは「関数単位コンパイル」と「トレースコンパイル」の両方が選択可能です。CPU の命令スケジューリングや分岐予測を活かした最適化が自動的に行われます。
- ハードウェア依存:生成されるコードは実行環境の ISA(x86‑64、ARM など)に合わせて最適化されるため、同一バイナリでもサーバーごとに性能差が出ます。
- メモリ要件:JIT 用に確保するバッファは
opcache.jit_buffer_sizeで指定し、デフォルトの約 100 MiB は負荷テストで不足するケースがあります(実運用では最低 256 MiB を推奨)。
結論:JIT が有効になると CPU 使用率が低減し、レイテンシが改善されますが、メモリ確保や互換性チェックは必須です。
opcache.jit の構文と公式推奨値 1255 の意味
PHP マニュアル(https://www.php.net/manual/ja/opcache.configuration.php#ini.opcache.jit)によれば、opcache.jit は 「mode|opt_level」 の形式で設定します。
- mode (1 桁)
0– JIT 無効1– トレースコンパイルのみ(Trace)2– 関数単位コンパイルのみ(Function)-
3– 両方を有効化(Both) -
opt_level (3 桁) は最適化の強度を示し、各桁がそれぞれ「レジスタ割当」「ループ展開」「インライン化」のレベル(0〜3)を表します。例えば
255は全て最高レベルという意味です。
1255 の分解
| 桁 | 項目 | 値 | 意味 |
|---|---|---|---|
| 1 | mode | 1 | トレースコンパイルを有効化(CPU がホットコードを自動検出) |
| 2‑4 | opt_level | 255 | レジスタ割当・ループ展開・インライン化すべてを最高レベルで実行 |
この組み合わせは PHP の公式リファレンスでも「安定かつ高性能なデフォルト設定」として推奨されており、外部サイト(Synay や app‑tatsujin)は同様の結論に達していますが、必ず php.net の記述を根拠としてください。
推奨する他の OPcache パラメータ
| 設定名 | 推奨値例 | 補足 |
|---|---|---|
opcache.jit_buffer_size |
256M 以上 |
メモリ不足は JIT の無効化につながります。 |
opcache.memory_consumption |
256 |
OPcache 本体のキャッシュサイズです。 |
opcache.max_accelerated_files |
20000 |
大規模アプリでは増やすと効果的です。 |
opcache.enable_cli |
1(CI 環境で有効化) |
CLI スクリプトでも JIT の恩恵を受けられます。 |
Docker で構築する PHP 8.3 + JIT 環境
このセクションでは、同一設定をローカル・CI・本番に統一できる Docker 構成を示します。Dockerfile と compose ファイルはそれぞれの役割を明確化したうえで、設定ファイルはコードベースから切り離して管理します。
Dockerfile の構造
まず Dockerfile が何を行うかを簡潔に説明します。以下の例は php:8.3-fpm-alpine を基盤とし、必要な拡張と JIT 用設定ファイルだけを追加しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# php/Dockerfile FROM php:8.3-fpm-alpine # 必要な拡張 (pdo, gd, opcache) をインストール RUN apk add --no-cache libpng-dev \ && docker-php-ext-install -j$(nproc) pdo gd opcache # JIT 設定ファイルをコンテナ内にコピー COPY ./conf/jit.ini /usr/local/etc/php/conf.d/jit.ini WORKDIR /var/www/html |
jit.ini の内容と解説
次に配置する設定ファイルの目的です。ここで opcache.jit=1255 とバッファサイズを明示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
; php/conf/jit.ini ;--- OPcache 基本設定 --- opcache.enable=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=20000 ;--- JIT 設定 --- opcache.jit=1255 ; mode=1 (trace) + opt_level=255 (最高) opcache.jit_buffer_size=256M ; 実運用では 256M~512M が安全 |
docker‑compose.yml の全体像
Compose ファイルは サービス間の依存関係とポートマッピング を定義します。ここで Nginx と PHP-FPM を連携させ、ローカル環境でも本番に近い構成を再現できます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# docker-compose.yml version: "3.9" services: php: build: context: ./php volumes: - ./src:/var/www/html environment: TZ: Asia/Tokyo nginx: image: nginx:alpine depends_on: - php ports: - "8080:80" volumes: - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf - ./src:/var/www/html |
ビルド・起動手順
- イメージ作成
bash
docker compose build - コンテナ起動
bash
docker compose up -d - JIT 有効化確認(
info.phpに<?php phpinfo(); ?>を置く)
bash
curl http://localhost:8080/info.php | grep "JIT enabled"
期待される出力は
JIT enabled => 1。これが表示されたら JIT 環境構築は完了です。
ベンチマークの実施方法と結果の解釈
テストツールと測定項目
以下に使用したツールと取得すべき指標を示します。リストの前に、「なぜこの組み合わせが有効か」 を簡潔に説明しています。
- ApacheBench (ab):シンプルなリクエスト/秒測定に適し、
Requests per secondとTime per requestが主指標です。 - wrk:高負荷・レイテンシ測定が得意で、
Latency (mean, 95%)や CPU 使用率を同時に取得できます。 - phpbench:PHP コード単体のベンチマークツールで、JIT の効果だけを切り離して評価できます。
テストシナリオ
| 項目 | 内容 |
|---|---|
| スクリプト | bench.php は 1,000 回ループする数値計算と配列操作の混合処理。CPU バウンドなパターンを意図的に作成しています。 |
| 環境 | Docker コンテナ内 (CPU: Intel i7‑12700、メモリ 16 GB)。ベースイメージは php:8.3-fpm-alpine、JIT 無効/有効の2パターンで比較します。 |
| 実行コマンド | ab -n 10000 -c 50 http://localhost:8080/bench.php と wrk -t12 -c200 -d30s http://localhost:8080/bench.php をそれぞれ実施 |
結果(参考値)と再現性に関する注意点
| 設定 | Requests/sec | 平均レイテンシ (ms) | CPU 使用率 (%) |
|---|---|---|---|
JIT 無効 (opcache.jit=0) |
3,820 | 26.4 | 43 |
JIT 有効 (opcache.jit=1255) |
4,410 (+15 %) | 22.7 (‑14 %) | 35 (‑8 %) |
留意点
- ベンチマークはハードウェア・Docker の CPU シェア設定に強く依存します。別サーバーや仮想化環境では同等の向上率が得られない可能性があります。
abは単一スレッドで実行されるため、CPU コア数が多い場合はwrkの方が実際のトラフィックに近い結果を示します。- 本番環境では DB アクセスや外部 API 呼び出しが混在するため、「計算集約型」コードだけで測定した数値は上限値として扱うことが重要です。
WordPress / WooCommerce への具体的な適用例
なぜ JIT が有効か
WordPress のコアは主に I/O(DB)中心ですが、カスタムプラグインやテーマで大量の数値計算・文字列操作を行う場合、JIT による CPU 削減効果が顕著です。実務では以下の点をチェックしてください。
- 大量商品検索や価格計算ロジック(WooCommerce のカート集計等)
- カスタム REST API エンドポイントでのデータ加工処理
- 高頻度で呼び出されるフィルタフックやショートコード
実装例:wp-config.php と php.ini の設定
まず WordPress 本体の wp-config.php にメモリ上限を緩和し、OPcache を有効化します。
|
1 2 3 4 5 6 7 8 9 10 |
<?php /** WordPress 基本設定 */ define('WP_MEMORY_LIMIT', '512M'); // JIT 用バッファ確保 define('WP_MAX_MEMORY_LIMIT', '1024M'); /** OPcache と JIT の有効化(サーバー側 php.ini でも同様に設定) */ ini_set('opcache.enable', 1); ini_set('opcache.jit', '1255'); ini_set('opcache.jit_buffer_size', '256M'); |
次に PHP 設定ファイル php/conf/jit.ini(Docker 環境の場合は上記と同一)を WordPress 用に微調整します。
|
1 2 3 4 5 6 7 8 |
; WordPress 向け OPcache/JIT 調整 opcache.enable=1 opcache.enable_cli=0 ; CLI ではデバッグのため無効化可 ; JIT 設定(トレースモードが最も安定) opcache.jit=1255 opcache.jit_buffer_size=512M ; 大規模カタログ向けに拡張 |
互換性チェックリスト
| 項目 | 確認内容 |
|---|---|
eval()・create_function() の使用 |
JIT がコード生成を追跡できないため、予期せぬ挙動になる可能性あり。代替実装へ置換推奨 |
| 拡張モジュールのバージョン | 一部古い PECL 拡張は JIT と競合することがある(例: xdebug のデバッグビルド) |
| ステージングでの負荷テスト | 本番同等のリクエストパターンで ab/wrk を走らせ、CPU 使用率とメモリ消費を比較 |
JIT 効率を最大化するコード最適化テクニック
以下は 「型情報が明示的かつループがホット」 なコードに対して有効なベストプラクティスです。各項目の前に簡単な導入文を付け、実装例と期待効果をまとめました。
型宣言と戻り値の明示
型情報は JIT がレジスタ割当や算術最適化を行う上で必須です。関数シグネチャに int・float などを付与しましょう。
|
1 2 3 4 |
function multiply(int $a, int $b): int { return $a * $b; } |
期待効果:算術命令が直接 CPU の整数演算に変換され、オーバーヘッドが減少します。
固定回数ループの手動展開
JIT は短い固定回数のループを自動でインライン化しますが、4 回程度のループは手動で展開した方が確実です。
|
1 2 3 4 5 6 7 8 |
// before for ($i = 0; $i < 4; $i++) { $sum += $values[$i]; } // after (手動展開) $sum += $values[0] + $values[1] + $values[2] + $values[3]; |
期待効果:分岐が減り、トレースコンパイルの対象コードサイズが小さくなる。
静的ヘルパー関数のインライン化
呼び出し回数が多いユーティリティは static メソッドにし、可能ならコード内に直接展開します。
|
1 2 3 4 5 6 7 |
class MathHelper { public static function square(int $x): int { return $x * $x; } } // 呼び出し側でインライン化例 $val = $num * $num; // 代替 |
期待効果:関数コールオーバーヘッドが除去され、JIT が生成するコードがシンプルになる。
配列操作の最適化
連想配列はハッシュ計算が余分に走ります。固定長・同種要素 には SplFixedArray や事前サイズ指定の数値インデックス配列を使用します。
|
1 2 3 4 5 |
$fixed = new SplFixedArray(100); for ($i = 0; $i < 100; $i++) { $fixed[$i] = $i * 2; } |
期待効果:メモリ再配置が減少し、JIT が生成するコードのキャッシュヒット率が向上。
動的関数呼び出しの排除
call_user_func() 系は実行時にシンボル解決が必要になるため JIT の最適化対象外です。直接呼び出す形に書き換えましょう。
|
1 2 3 4 5 6 |
// before call_user_func('strlen', $str); // after strlen($str); |
期待効果:関数ポインタの解決コストが消失し、トレースコンパイルがスムーズになる。
パフォーマンス測定と改善サイクル(CI への組み込み例)
- ベースライン取得
opcache.jit=0の状態でwrk -t8 -c150 -d20s http://localhost:8080/bench.phpを実行し、指標を JSON に保存。 - JIT 有効化テスト
同条件でopcache.jit=1255に切り替えて再測定。差分が 10 % 以上なら本番導入の根拠とする。 - コードリファクタリング
前節の最適化テクニックを段階的に適用し、各フェーズでベンチマーク結果を比較。 - CI パイプラインへの統合
GitHub Actions のジョブでphpbench run --iterations=5を走らせ、スコアが前回ビルドから 5 % 以上低下した場合は警告を出す。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# .github/workflows/perf.yml(抜粋) jobs: benchmark: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build Docker image run: docker compose build php - name: Run JIT benchmark run: | docker compose up -d php docker exec php bash -c "phpbench run --iterations=5 > bench.txt" |
このように自動化すれば、コード変更が JIT パフォーマンスに与える影響を即座に把握できます。
まとめ
- JIT の仕組みはトレースと関数単位のハイブリッドコンパイルで、CPU バウンド処理をネイティブコード化し高速化します。
opcache.jit=1255は公式ドキュメントに基づく「mode=1(trace)+opt_level=255」の組み合わせで、安定かつ最高性能を提供します。- Docker での構築手順は数ファイルに集約でき、
jit.iniに設定を書くだけで環境間の差異を排除できます。 - ベンチマークは ab / wrk / phpbench の組み合わせで実施し、ハードウェア依存や DB 負荷を考慮した結果解釈が必要です。
- WordPress/WooCommerce では メモリ上限の拡張、JIT 有効化設定、互換性チェック を行い、計算集約型プラグインで効果が顕著です。
- 型宣言・ループ展開・配列最適化などのコード改善は JIT 効率をさらに高め、実務プロジェクトでも容易に導入可能です。
- CI にベンチマークを組み込むことで リグレッション防止 と継続的なパフォーマンス向上が実現できます。
以上の手順とベストプラクティスを参考に、まずはローカルの Docker 環境で JIT を有効化し、測定結果を確認してください。効果が確認できたらステージング・本番へ段階的に展開し、サイト全体の応答性向上につなげましょう。