10.2K Views
July 17, 25
スライド概要
どこまで違う?! PHP実行環境パフォーマンス対決 - mod_php vs php-fpm vs Swoole vs FrankenPHP
目次 1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 2
導 入 3
比較・検証する環境 今回は4つのPHP実行環境のパフォーマンス検証 Apache + mod_php Nginx + PHP-FPM Swoole + Nginx FrankenPHP 4
実行シナリオ概要 テストタイプ:ストレステスト シナリオ概要:ユーザーが記事を投稿して、 投稿した記事を複数のユーザーが閲覧しに来る テストタイプ:スパイクテスト シナリオ概要:セール予告後のような急激な閲覧者増によるトラフィック増加に対する 5
ソースコード詳細はGitHubで公開中 https://github.com/gmagmeg/performancecomparison/tree/main 6
それぞれの環境でどうなるか 想定しながらお愉しみください 7
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 8
プロフィール・所属会社紹介 発表者 ma@me(SNS:ma_me) 所属 直近の登壇 PHP実行環境の歴史 PHP-FPMからFrankenPHPの誕生へ 9
PHPエンジニア 募集中! https://booost.inc/RECRUIT 10
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 11
各環境紹介 Apache + mod_php NTS(Non Thread Safe) プロセスベース ApacheのモジュールとしてPHPが直接組み込まれる形式 リクエストごとにプロセスが処理されるため、 リクエスト数に伴ってメモリ使用量が大きくなりがち 設定がシンプルで歴史も長い。 レガシーシステムで採用されている定番構成 12
Nginx + PHP-FPM NTS(Non Thread Safe)、マルチプロセス形式 NginxとPHP-FPM(FastCGI Process Manager)が別プロセスで動作する プロセスプールによるリソース管理で、 高トラフィック時の安定性とメモリ効率が優秀 13
Nginx + Swoole NTS版とZTS版の両方が存在(コルーチンはシングルスレッドで動作) PHPの非同期I/O拡張で、コルーチンベースの並行処理を実現 常駐プロセスでリクエストを処理するため高速 14
Swooleの補足事項 Swoole自体組み込みWebサーバーを持っています が、餅は餅屋。Webサーバーを立てることを公式も推奨。 15
FrankenPHP ZTS(Zend Thread Safe)、マルチスレッド形式 Go言語で実装されたPHPのSAPIで、Caddyサーバーに統合されている ワーカーモードによるアプリケーション常駐化で 起動オーバーヘッドを削減 16
FrankenPHPの補足事項 2025年5月 PHP Foundationからのオフィシャルサポートを受けることが決定 FrankenPHP Is Now Officially Supported by The PHP Foundation — The PHP Foundation — Supporting, Advancing, and Developing the PHP Language 17
より詳細な実行環境 より詳しい詳細はこちらのスライドで説明しています(宣伝) https://www.docswell.com/s/1313108/ZP2QQ1-2025-03-21-123847 18
用語紹介 1 NTS(Non Thread Safe) 2 ZTS(Zend Thread Safe) PHPには2つのビルドバージョンがあります それぞれ異なる実行環境に最適化されています 19
ZTS(Zend Thread Safe) マルチスレッド環境で異なるスレッドが 同一リソース(同一メモリや同一変数)にアクセスして も問題ないように、排他機構を持つ 排他機構のオーバーヘッドで、そのまま扱うとNTSより 処理速度が低下する 20
NTS(Non Thread Safe) 現在のほとんどの本番環境で採用されている シングルスレッド環境向けに最適化されたビルド 排他機構を持たなくていい分、オーバーヘッドなし 21
計測環境・計測ツール紹介 各環境共通アプリケーション基盤 PHP MySQL 8.3.20 8.0 Laravel 12.0 Docker 22
異なる構成部分 ZTS構成 NTS構成 Laravel 12 + Octane Laravel 12 (ZTS向けに最適化するライブラリ) 対象実行環境 対象実行環境 Swoole + Nginx (Laravel Octane) Apache + mod_php FrankenPHP (Laravel Octane) Nginx + php-fpm 23
計測ツール k6 OpenTelemetry 負荷検証 プロファイリング OpenTelemetryを選んだ理由 そもそもZTS環境に対応したプロファイリングツールが少ない 詳細: https://zenn.dev/booost/articles/a691d0fe7aeae6 24
詳細はこちら 詳細なコードと設定はGitHubリポジトリで公開しています。 https://github.com/gmagmeg/performance-comparison 25
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 26
負荷試験シナリオ1 - アベレージロードテスト ℹ️概要 ユーザーが記事を投稿する 投稿した記事を複数のユーザーが閲覧しに来 る 🎯目的 多数のユーザーによる同時アクセ ス時の レスポンス性能 と 安定性 を評価す る 27
🧪試験概要 ユーザー行動: 記事投稿 1回につき、記事閲覧が10回発生する 負荷増加: 開始60秒で最大80ユーザー/秒まで増加させる 維持時間: 最大負荷で3分間維持する 4分間でおおよそ6500回のリクエストが発生 ✅ 合格基準 (SLO) 記事投稿 (P90): 3秒以内 記事閲覧 (P90): 1秒以内 エラーレート: 0.1% 未満 28
アプリ概要 から api/read-weight にPOST・GETリクエスト 計:9テーブルに書き込み&読み取る 29
対象テーブル 1 users 2 posts 3 categories 4 tags 5 comments 6 post_views 7 likes 8 post_tags 9 post_categories 30
該当のソースURL https://github.com/gmagmeg/performance-comparison/blob/main/newapache/app/Http/Controllers/Api/PostWeightController.php https://github.com/gmagmeg/performance-comparison/blob/main/newapache/app/Services/PostWeighService.php 31
📢 計測結果発表 32
の前に 用語紹介 Part2 1 パーセンタイル 2 スループット これらを知っていると、計測結果がより分かりやすくなります 33
パーセンタイル(p90, p95) 応答時間の分布を示す指標。数値が少ないほどいい 90%・95%のリクエストが実際にこの時間内に完了したことを表す。 例:10個のリクエストの応答時間 9個: 100ms、1個: 10,000ms(10秒) 平均値:1,090ms ← 実際に体験したユーザーはいない P90:100ms(90%のリクエストは100ms以内) ← 実際にユーザーが体験した数値 P95:100ms(95%のリクエストは100ms以内) ← 実際にユーザーが体験した数値 34
スループット 単位時間あたりの処理能力 1秒間に処理できるリクエスト数(RPS) システムの処理能力を直接表す指標 数値が高いほどいい 多くのユーザーに対応可能 35
あらためて 📢 計測結果発表 36
どの環境もエラーは無し! 素晴らしい! 👏 37
🖥️ リソース使用量比較 CPU使用率とメモリ使用量の比較 環境 平均CPU使用率 平均メモリ使用量 Apache+mod_php 35.77% 360.08 MB Nginx+PHP-FPM 34.32% ⭕190.75 MB Nginx+Swoole 32.03% 962.90 MB FrankenPHP ⭕20.47% 288.40 MB swooleとphp-fpmはNginxサーバーとの合算値 38
▶️ PHP実行環境比較結果 レスポンス時間とスループットの比較 環境 P95レスポンス P90レスポンス スループット Apache+mod_php 36.91 ms 27.99 ms 28.49 RPS Nginx+PHP-FPM 33.77 ms 25.54 ms 28.06 RPS Nginx+Swoole FrankenPHP ⭕27.15 ms ⭕20.51 ms ⭕28.58 RPS ⭕25.82 ms ⭕19.51 ms ⭕28.65 RPS 39
P95ベースで速度差異を可視化(外部ページへ) https://gmagmeg.github.io/performance-comparison/ 40
➡️ レスポンス時間詳細比較 各処理別のレスポンス時間(P95) 環境 POST処理(記事作成) GET処理(記事取得) Apache+mod_php 49.61 ms 22.45 ms Nginx+PHP-FPM 50.53 ms 20.69 ms ⭕45.64 ms ⭕45.86 ms ⭕16.38 ms ⭕15.48 ms Nginx+Swoole FrankenPHP 41
POSTのP95ベースで速度差異を可視化(外部ページへ) https://gmagmeg.github.io/performancecomparison/post.html 42
📢 計測結果総評 リソース効率 全環境でエラー発生なし(100%安定性) CPU効率: FrankenPHP > Swoole > 従来構成 メモリ効率: Nginx+PHP > FrankenPHP > Apache > Swoole 補足 Nginxはサーバーとphp-fpmでメモリが分散 Swooleはメモリにプロセスを常駐させるため、他と比べて消費率高 43
レスポンスパフォーマンス面 FrankenPHP・Swooleが総合的に最優秀 (レスポンス・CPU効率) Apache, Nginxと比較で ⇧30-40%の性能向上を実現 44
一番遅いApacheと 一番早いFrankenPHPで11msの差 環境 P95レスポンス P90レスポンス スループット Apache+mod_php 36.91 ms 27.99 ms 28.49 RPS FrankenPHP 25.82 ms 19.51 ms 28.65 RPS 差 -11.09 ms -8.48 ms +0.16 RPS 45
11msの速度差異を可視化(外部ページへ) https://gmagmeg.github.io/performance-comparison/apachediff-franken.html 46
🤔ここまで見て、多少差はあれど 意外と大差が付かなかったようにも 見えたのではないでしょうか 47
ここで影の立役者の登場 OPcache 48
⇔ Apache+mod_php OPcache比較 - リソース使 用量 同じ環境でもこれだけの違いが出ます 項目 OPcache無し OPcache有り 平均使用CPU 290% 48%(83%削減) 平均使用メモリ 2.18 GiB 462.10 MB(79%削減) (CPUコア4つのため、100%越え) 49
⇔ Apache+mod_php OPcache比較 - レスポンス 性能 項目 OPcache無し OPcache有り 平均レスポンス 90.31 ms 18.46 ms(80%改善) P90レスポンス 119.35 ms 27.99 ms(77%改善) P95レスポンス 130.59 ms 36.91 ms(72%改善) 50
Opecacheの有無で速度差異を可視化(外部ページへ) https://gmagmeg.github.io/performance-comparison/apachediff.html 51
⇧OPcacheの導入により大幅な性能改善 この簡易設定でも効果 大⇧ - OPcache.enable=1 // 有効にする - OPcache.enable_cli=1 // cliモードでも有効にする - OPcache.memory_consumption=128 // キャッシュサイズの指定 WebサーバーやDBのチューニングも重要だけれど PHPのチューニングも大切 52
OPcacheの話は一旦おしまい。 よりWebサーバーの性能差が出る検証を見ていきます 53
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 54
負荷試験シナリオ2 - スパイクテスト ℹ️概要 セール予告後のような急激な閲覧者増による トラフィック増加に対する負荷試験 🎯目的 急激なアクセス増加時の レスポン ス性能 と 安定性 を評価する 55
🧪試験概要 開始: 0ユーザーから10秒で10ユーザーに増加 スパイク: 20秒で200ユーザー/秒まで急激に増加 終了: 10秒で0ユーザーに減少 総試験時間: 40秒間でトラフィックパターンを実行 ✅ 合格基準 (SLO) レスポンスタイム (P95): 2秒未満 エラーレート: 1% 未満 56
から api/read-weight にGETリクエスト(POSTなし) 計:9テーブルのデータを読み取り、JSONを返す 1 users 2 posts 3 categories 4 tags 6 post_views 7 likes 8 post_tags 9 post_categories 5 comments 57
JSONサンプル 58
該当のソースURL https://github.com/gmagmeg/performance-comparison/blob/main/newapache/app/Http/Controllers/Api/ReadWeighController.php 59
⚡スパイクテスト 計測結果発表 60
🖥️ リソース使用量比較 CPU使用率とメモリ使用量の比較 サーバー 平均CPU使用率 平均メモリ使用量 Apache+mod_php 66.86% 648.09 MB Nginx+PHP-FPM 45.81% ⭕165.59 MB Nginx+Swoole ⭕36.87% 980.35 MB FrankenPHP ⭕37.16% 288.75 MB swooleとphp-fpmはNginxサーバーとの合算値 61
⏱️ レスポンス時間比較 単一サーバーで受けようとすると、Apacheは厳しい結果に サーバー p(90) p(95) スループット エラー率 Apache+mod_php 68.92 ms 1.68 s 35.90 RPS ×2.19% Nginx+FPM 22.15 ms 24.72 ms 38.10 RPS ⭕0.00% Swoole ⭕18.38 ms ⭕21.33 ms ⭕39.10 RPS ⭕0.00% FrankenPHP ⭕18.90 ms ⭕21.44 ms ⭕39.50 RPS ⭕0.00% 62
スパイクテストの速度差異を可視化(外部ページへ) https://gmagmeg.github.io/performancecomparison/spike.html 63
📢 計測結果総評 高負荷耐性 非同期処理系(Swoole、FrankenPHP)は安定した低レイテンシーを維持 従来プロセス管理(Apache mod_php)は性能劣化とエラー発生が目立った リソース効率 メモリ効率: PHP-FPM > FrankenPHP > Apache > Swoole CPU効率: Swoole ≈ FrankenPHP > PHP-FPM > Apache 64
負荷シナリオ1・2総評 通常負荷時(シナリオ1) 全環境で安定動作、差は僅差 全環境でOPcacheの効果が絶大(80%の性能向上) FrankenPHP・Swoole+Nginxが総合的に最優秀 高負荷時(シナリオ2) 環境間の性能差が顕著に現れる 従来のApache構成では限界が露呈 ZTS・NTS環境が高負荷耐性で優位性を発揮 65
🤔 パフォーマンスがいい方に 乗り換えるのが正解か? 66
🤔アプリケーションの状態で考える 大切な前提 そもそも課題がないないのなら 無理に変える必要はない Apache + mod_php環境であっても 課題がないのなら変える必要はありません。 Apacheもバリバリ更新中 67
課題がある場合:アプリケーションの利用用途で 考える アプリケーションが読み取り主体 Webサーバー・PHPのチューニングが効果的 このスライドの内容が役立てばうれしいです アプリケーションが書き込み主体 DBのチューニングが効果的 68
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 69
1. OPcacheを使う 2. early hints(103)対応 3. Symfonyのドキュメントを参照する 70
1. opcacheを使う 再掲 - opcache.enable=1 // 有効にする - opcache.enable_cli=1 // cliモードでも有効にする - opcache.memory_consumption=128 // キャッシュサイズの指定 71
2. early hints(103)対応 サーバーが最終的なレスポンス(200 OK等)を準備している間に、 ブラウザに対してリソース(CSS、JavaScript等)の先読みを 指示する仕組み(プリロード) では 2~3ms の短縮を確認 72
Apache, Nginxも直近で対応済み このプレゼンまでには間に合いませんでした... ver:1.29.0 2025年6月24日リリース モジュール:HTTP/2 https://httpd.apache.org/docs/current/howto/http2.html #page-header 73
early hintsのFrankenPHPの対応状況 early hints(103)は組み込み済み PHPのコードに headers_send(103); と書くだけでOK。とても楽。 74
3. Symfonyのドキュメントを参照する https://symfony.com/doc/current/performance.html 75
に関わらず役立つ情報がたくさん OPcacheの最適な設定値 composer の最適なinstall時の設定 など 76
Apache + mod_phpやNginx + PHP-FPMでも 改善できることはちゃんとある! 77
1 導入 2 プロフィール・所属会社紹介 3 各環境・用語・計測ツール紹介 4 負荷シナリオ1 - アベレージロードテスト 5 負荷シナリオ2 - スパイクテスト 6 総評と選択指針 7 環境を向上させるTips3選 8 まとめ 78
Apache + mod_php 適用シーン: 既存継続運用。情報が豊富 主なメリット: 設定が簡単で、安定性が高い 注意点: 1台で高負荷を受けると性能が劣化する LBを設置してサーバー分散すれば、問題点も解消しやすい 79
Nginx+PHP-FPM 適用シーン: バランス重視。現在最も普及している構成。 主なメリット: サーバーを分散する前提なので、 低メモリで安定性が高い。 注意点: 1台1台のリソース効率が最も良好だが、 PHP+Webサーバーでサーバー台数が増えがち 80
Swoole 適用シーン: 高性能要求。リアルタイム性が重要なシステム 主なメリット: 最速レスポンス。コルーチンによる非同期処理 注意点: メモリ消費が大きい。 チューニング項目が多岐にわたる 常駐プロセスのため、 メモリリークに注意が必要 81
FrankenPHP 適用シーン: 簡単に高性能要求を実現したい 主なメリット: 簡単にいい性能を取りやすい (Early Hints標準対応など) 注意点: 新しい技術のため情報が少ない 実運用例も少ない 82
皆さんの実行環境選択の助けになれば幸いです ご清聴ありがとうございました 一言でもフィードバックいただけると嬉しいです forteeのフィードバックページ 83