Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP Web Application Performance Tuning
Search
shiro seike
PRO
March 27, 2021
Programming
9
4k
PHP Web Application Performance Tuning
https://phperkaigi.jp/2021
shiro seike
PRO
March 27, 2021
Tweet
Share
More Decks by shiro seike
See All by shiro seike
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
90
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
510
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
1.1k
実践サーバーレスパフォーマンスチューニング ~その実力に迫る~ / Practical Serverless Performance Tuning ~A Close Look at its Power~
seike460
PRO
2
350
PHPを書く理由、PHPを書いていて良い理由 / Reasons to write PHP and why it is good to write PHP
seike460
PRO
5
590
AWS CDKを用いたセキュアなCI/CDパイプラインの構築 / Build a secure CI/CD pipeline using AWS CDK
seike460
PRO
3
750
いまあるチームにフィットさせる Serverless そして Platform Engineeringへの挑戦 / Serverless Fits the Team You Have and Platform Engineering
seike460
PRO
2
2.1k
いまあるチームにフィットさせる Serverless / Serverless fits in with the team you have now.
seike460
PRO
2
180
地方こそサーバーレス! チームにフィットさせるサーバーレス / Rural areas are serverless! Serverless to Fit Your Team
seike460
PRO
1
120
Other Decks in Programming
See All in Programming
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
110
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
200
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1k
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
Security_for_introducing_eBPF
kentatada
0
110
Symfony Mapper Component
soyuka
2
730
17年周年のWebアプリケーションにTanStack Queryを導入する / Implementing TanStack Query in a 17th Anniversary Web Application
saitolume
0
250
HTTP compression in PHP and Symfony apps
dunglas
2
1.7k
今年のアップデートで振り返るCDKセキュリティのシフトレフト/2024-cdk-security-shift-left
tomoki10
0
190
tidymodelsによるtidyな生存時間解析 / Japan.R2024
dropout009
1
740
Haze - Real time background blurring
chrisbanes
1
510
コンテナをたくさん詰め込んだシステムとランタイムの変化
makihiro
1
120
Featured
See All Featured
How GitHub (no longer) Works
holman
311
140k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
GraphQLとの向き合い方2022年版
quramy
44
13k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Into the Great Unknown - MozCon
thekraken
33
1.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
Visualization
eitanlees
146
15k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Reflections from 52 weeks, 52 projects
jeffersonlam
347
20k
RailsConf 2023
tenderlove
29
940
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.9k
Unsuck your backbone
ammeep
669
57k
Transcript
PHPWebアプリケーション パフォーマンスチューニング PHPerKaigi 2021 2021.3.27 清家史郎 1
速いは正義、アプリケーションは速くあるべきです インターネットの高速化やハードウェア性能の向上により アプリケーションはよりパフォーマンスを求められるようになってきています PHPの力を最大限発揮して、より高速なインターネット体験を提供しましょう 2
自己紹介 清家 史郎 @seike460 - ID - GitHub:seike460 -
Twitter:@seike460 - Work at - 株式会社 Fusic (フュージック) 技術開発本部/技術開発第一部門 - チームリーダー/エバンジェリスト/プリンシパルエンジニア - Skill - PHP/Go/AWS - Personal - PHPカンファレンス福岡2020 幻の実行委員長 - Fukuoka.php Organizer - 46fm パーソナリティ 3
Agenda 4 1. PHPWebアプリケーション構成要素 2. 計測 3. パフォーマンス改善 4.
まとめ 5. Appendix
01 PHPWebアプリケーション 構成要素
PHPWebアプリケーション構成要素 6 一般的なWebアプリケーションの構成は大きく分類して 以下の用に分類される事が多く、それぞれに対してパフォーマンスを改善を行います - Webサーバ -
アプリケーションサーバ - DBサーバー
Webサーバ 7 ウェブブラウザに対して、HTMLや画像などの表示を提供したり、 アプリケーションサーバへのリバースプロキシを受け持ちます
アプリケーションサーバー 8 Webサーバからのリクエストに応じて処理を行い、 DBサーバとやり取りをしてレスポンスを構築する
DBサーバー 9 リレーショナルデータベース(RDB) PHPからの要求に応じて、データ登録、更新、削除、参照を行います ※ストレージとしてRDB以外を選択することもあります
ハイパフォーマンスであること 10 スループット 単位時間当たりの処理能力 一般的に1秒間に返せるリクエストを表すrps(Request Per Second)が用いられます レイテンシー リクエストからレスポンスまでに生じる通信の遅延時間 一般的に単純な時間であるmsが用いられます
ボトルネック 11 パフォーマンスを下げる原因となる処理能力が低いポイント 様々なボトルネックがあります - Webサーバパラメータ - PHPコードの問題 -
DB設計ミス 経験を積んでいくと「この現象はこれっしょ」という推測が立つようになる この長年の勘に頼ることは再現性がなく不確実
推測するな、計測せよ ボトルネックを特定するまで推測で行動しない 計測した「データ」を元に原因を特定して、対策を講じる 12
長年の勘ではなく、理論に従う 13 信頼のおけるデータを正しく理解して対策を行う事で再現性を確保する。 パフォーマンス改善には次のステップを踏む必要があります。 - 現在の状況を把握するために、計測を行う -
計測で集まったデータを元に考察して、原因を特定する - 特定した原因に対して、正しく改善する 愚直にこのサイクルを回す事が重要
02 計測
サーバ負荷の確認
スループット測定 16 スループットを測定するためのツールとして今回はLocustを利用します。 Python製ではありますが、少しづつ負荷を上昇させることが出来るため、 そのWebアプリケーションのスループットの閾値を測定することが出来ます。
負荷の確認 17 スループットの閾値に到達した際に、閾値を決定づけるボトルネックを探します。 ボトルネックになってるサーバを探す際に各サーバのリソース状況を参照します。 - 処理待ち状況、CPUの負荷 -
ディスクの負荷 - メモリの負荷
処理待ち状況、CPUの負荷 18 サーバの処理待ちの状況を確認するにはLoad Averageを確認します。 初期アプローチとしては処理コストが少ない「uptime」を使うのが適切です。 CPU状況も合わせて確認するには「htop」を使うと便利です。
CPUのコア数以上の処理待ちがある場合、 そのサーバーがボトルネックになっている可能性が高いです。
ディスクI/Oの状況 19 ディスクはデータの読み書きをする上で、一番低速な機器となります。 ディスクI/Oが大きい時は、パフォーマンス劣化の原因になっている事が多いです。 「vmstat」でディスクの読み込み、書き込みを確認する事が出来ます(bi / bo)
メモリの負荷 20 メモリを100%使い切っている場合、スワップメモリを利用することになります。 スワップメモリは、ディスクをメモリ領域として確保して利用する為、 実質ディスクI/Oを発生させる事になります。 ディスクは非常に低速なデータ領域なのでボトルネックになる可能性が高いです。
「htop」や「vmstat」でスワップメモリの状況を確認出来ます。
ボトルネック処理の特定
PHPのパフォーマンス測定 22 PHPに原因がありそうな事がわかった場合、 どの関数で問題が発生しているのかをプロファイラーを用いて確認します。 OSSになっているXdebugが比較的気軽に導入することが出来ます。
費用に余裕がある場合は、DatadogやBlackfire等の SaaSを利用することも選択肢にあがります。
Xdebug x Webgrind 23 Xdebugにてプロファイルを取得して プロファイル解析が可能なWebgrindを利用し、Graphvizを介して可視化します。 具体的な利用方法はこちらの記事をご確認ください。
すると右図の用に図が生成出来ます。 - どの関数から呼び出されているか - 処理を専有している関数 - 繰り返し実行されている回数 N+1問題等を発見して解消していきます
RDBでのパフォーマンス測定 24 PHPプロファイリングにて時間がかかっているのがRDB操作の関数であったり、 DBサーバのリソース枯渇している場合、RDBにボトルネックがあることがわかります 単一のSQLが原因になっているのであれば実行計画を見ていきます。 DB設計ミスなのか、Index設定ミスなのか、
もしくは必要なリソースをRDB割り振れていないのかを判断していきます。
計測、考察、対策 25 このようにサーバのリソース計測したり、プロファイラを利用することで WebサーバやPHP、RDBの状態を正しく認識します。 現状を正しく認識したら原因について考察し、対策を実施します。
対策後、新たなボトルネックが判明したら、再度計測を行い繰り返し改善します。
03 パフォーマンス改善
DB
実行計画① 28 ◎あるSELECT SQLの実行が遅い場合 EXPLAIN(ANALYZE)をSELECTの前に付けて、実行計画を取ります。 - Seq Scan … 全レコード探索 - Index
Scan … Indexとテーブルに交互にアクセスして探索 - Bitmap Scan … メモリ上に展開されたBitmapを使ってAndOrの探索 - Index Only Scan … Indexのみからデータを探索(条件有) 意図したIndexが利用できているかを確認します。
実行計画② 29 テーブル結合にも注目します。 Nested Loop … 外部テーブルをスキャンして、内部テーブルに結合 Indexの概念があるので、意図したIndexが効いてるかを考慮 Merge Join … 外部テーブル、内部テーブルのキーをソートして結合
Indexがないテーブルではコストが大きい Hash Join … メモリ上にハッシュテーブルを作成してハッシュを比べて結合 メモリ上にハッシュテーブルが収まれば高速に結合
非正規化 30 必要以上にJoinが発生してしまう場合などは、 正規化しているテーブルの非正規化も検討を行います。 データの追加・更新・削除が発生しないテーブルに関して、 非正規化が有効で、Joinを減らすことでSQLのコストを下げることが出来ます。
パラメータチューニング 31 ◎DBサーバのリソースが有向活用出来ていない場合 CPUの使用率は高いが、メモリの使用率が低い場合などは、 RDBにメモリを十分に与える事で解決する可能性があります。 メモリを利用するソートやジョインが高速化され、
不必要なディスクI/Oを発生させずに結果を返すことが出来ます。 ディスクにデータを書き込むタイミングを調節することで、 ディスクI/Oを減らす事が出来ます。 RDBパラメータチューニングの内容はここでは話しきれないので、 Appendixを是非ご覧ください
Source、Replica 32 ◎DBサーバ複数台構成が組める場合 データ更新のディスクのI/Oが原因でSELECTが遅くなってしまう可能性があります。 そもそもの設計の話になりますが複数台構成を取り、データの更新はSourceに行い、 データの参照はReplicaに行うことでデータの参照を遅延させない事が出来ます。
PHP
PHPバージョンアップ 34 ◎問答無用でパフォーマンスアップの可能性 PHPは日々進歩しています。 PHPバージョンアップにより高速化する可能性は十分にあります。 SwooleTwitterアカウント (@php_swoole)より引用
オペコードキャッシュ 35 オペコードキャッシュの機構を使う事で更にPHPを高速化させる事が可能です。 OPcacheを利用することで、コンパイルしたコードをメモリ上にキャッシュし、 高速化することが出来ます。 初期設定では定期的にPHPコードの変更をチェックして、
変更があればファイルから再読み込みが行われます。
JIT JIT(ジャストインタイム・コンパイラー) PHP8から導入された機能 JITはOPCcacheの中間コードの重要な部分をネイティブコードまで変換します。 コンパイルをバイパスするおかげで、 パフォーマンスとメモリ使用状況を大幅に改善させる事が可能です。
36 php.netより引用
ユーザーキャッシュ 37 ◎DBサーバ負荷が高い ユーザーキャッシュの機構を使いKey Valueのキャッシュを利用することで、 ディスクアクセスを減らす事が可能です。 但しディスクのデータが更新された際のキャッシュクリアが必要になります。
- APCu - PHP単体で利用 - Redis - キャッシュサーバーとして複数台で利用
PHP 38 ◎Webサーバーからのリクエストを受けきれない フォークするプロセス数を増やす事で受け取るリクエスト数を増加させます。 - pm.max_children:同時に処理するプロセスの最大数 -
pm.start_servers:起動時に生成されるプロセス数 - pm.min_spare_servers:待ち状態の子プロセス最小数 - pm.max_spare_servers:待ち状態の子プロセス最大数 サーバーのリソースとmemory_limitの上限に相談して、 プロセスを増やすことで処理性能を上げる事が出来ます。 Apache + mod_phpの場合はMaxClientの設定に相当します。 パラメータチューニングの詳細は Appendixをご覧ください。
Webサーバー
Webサーバーのパフォーマンス 40 ◎クライアントからのリクエストを受けきれない 何らかの要因でスパイクアクセスが発生した際に、 WebサーバはそのHTTPリクエストを受け切る必要があります。 ApacheのMaxClientや、Nginxのworker_processesを調整します。
OSパラメータであるulimit等の値を調節して、 Too Many Open Fileが発生しない用にするなどの調整が必要になります。 設定例はAppindexへ
リソース圧縮 41 ◎ネットワークトラフィック HTMLやCSS等のリソースファイルを返還する際に、 データを圧縮して転送してブラウザに解凍してもらう事で ネットワークトラフィックを少なくすることも出来ます。
ブラウザで解凍する必要がありますので、 クライアントに若干の負荷をかける事になりますが、速度の向上に繋がります。
HTTP2 42 ◎HTTP/2を利用する 利用するプロトコルをHTTP/2に変更します。 1つのコネクション内で同時に並行して複数のリクエスト/レスポンスを処理出来る為 複数のリソースファイルを1つのコネクションで返す事が出来ます。
ファイルキャッシュ 43 ◎PHP以降の処理が重い HTMLやCSSをWebサーバーにキャッシュしてしまうのも手です。 PHPでSSRをする場合、結果が変わらない場合はWebサーバー側で PHPのレンダリング結果をメモリ上にキャッシュしてしまい、 PHPへのRequestを減らすことで、低負荷で高速に結果を返すことが可能です。
但しキャッシュクリアのタイミングを失敗すると想定している結果を返せず、 手動でキャッシュをクリアするなど障害が発生してしまう可能性があります。
まとめ Point 3 ボトルネックを解消する方法は様々な方法があります。知識を蓄え適切に対処しましょう。 44 推測するな、計測せよ。再現性のある対策を行いましょう。 Point 1 Point
4 話せないことがたくさんあった、Appendix見ていってください リソースを正しく把握して、ボトルネックを特定しましょう。ディスクアクセスは遅い。 Point 2
ご清聴いただきありがとうございました Thank You We are Hiring ! https://recruit.fusic.co.jp/
Appendix 05
Nginxパラメータチューニング 47 Webサーバーはいかにリクエストを受け付けるのかが鍵 ※メモリの消費に直結するのでサーバーリソースと相談しながら - worker_processes - 受け付けるNginxのプロセス数を決める。auto
= CPU数がオススメ - worker_connections - ひとつのワーカーが開けるConnection数 - worker_rlimit_nofile - 開けるファイルディスクリプタの上限値
PHPパラメータチューニング 48 Nginxからプロキシされたリクエストを受け切る必要がある 僕はパフォーマンスを追い求める時(ISUCON時など) サーバがリソース許せばプロセスフォークする負荷を発生させない為に、 待機プロセスを最大化しておく(1プロセスがmemory_limit分メモリを使うのに注意)
max_children * memory_limit ≒ サーバーメモリ + OS稼働分 + 余白 FastCGI Process Manager (FPM):設定 pm.max_children、pm.start_servers:起動、最大のプロセスを制御 pm.min_spare_server、pm.max_spare_server:フォーク後に待ち受けるプロセスを制御 ※mod_phpの場合はMaxClientsなどが対応します。
RDBパラメータチューニング 49 詳しい内容は下記から得た知識になります。 ◎僕が心の拠り所にしているQiita MySQLパフォーマンスチューニング -my.cnfの見直し- ◎@mamy1326 さん作成の元ネタ
初めてのMySQLサーバーチューニング -データベースは怖くない!- こちらを見て是非理解を深めてください。 次のページからはPostgreSQLの設定をいくつかご紹介します
RDSパフォーマンスチューニング 50 増やしたPHPのリクエストを受け切る為に接続数を上げます(max_connections) ただしその分だけメモリとディスクI/Oが増加する恐れがあるため、 あまりにも多くし過ぎると接続を許しながら LoadAverageをひたすら増加させる恐れがあります。
潔くtoo many clientsを出してLoadAverageの過剰な増加を防ぐのも一手です。 ※PHP側で正しく判定する必要が出てきます。
RDSパフォーマンスチューニング 51 利用するメモリを増やすことでメモリキャッシュを行ったり、 ソートやジョインで利用する際のメモリを増やす事で高速化を行います。 effective_cache_size … 単一の問い合わせで利用できるディスクキャッシュの実効容量 shared_buffers … データベースサーバが使用する共有メモリバッファ work_mem … 一時ディスクファイルに書き込む前に、 内部並べ替えとハッシュテーブル操作が使用するメモリ容量
RDSパフォーマンスチューニング 52 ログ先行書き込み(WAL)はデータの一貫性を確実にするための標準的な手法です。 ディスクに書き込む前にメモリ上に保管しておく事が出来、 メモリに保持する量や頻度を調節することにより、ディスクへの負荷を低減出来る checkpoint_timeout、max_wal_size、wal_buffers(-1で大抵の場合妥当な結果となる) 等が調整の対象となる。 29.4. WALの設定
距離 53 データ転送も距離の問題があります。 データやコンテンツとの通信の距離を短く設定する為にDNSやCDNで 高速化の仕組みを提供します。 - DNS:位置情報ルーティングポリシー(Route53など)
- CDN:エッジロケーション(Akamai、CloudFrontoなど)
CDN 54 CDNはコンテンツキャッシュの機能も有するので、 コンテンツをオリジン(配信元)から受け取った後にキャッシュして、 後続のサーバーへの負荷を減らすことが出来ます。(例のごとくTTLに注意)
JAMstack 55 JavaScript/APIs/Markupの頭文字をとったフロントエンドスタック (PHPでは無いですが) FusicのTechBlogはJAMstackを利用したSSGで運用しています。 パフォーマンス、スケーラビリティ、セキュアなブログ・サイトを運用出来てます。 弊社の浦田の登壇資料が分かりやすいのでご参照ください。
フロントエンド 56 本筋とはズレますが、フロントエンドのチューニングもあります。 - Rendering - CSS(CSSOMツリー) - HTML(DOMツリー)
- Scripting - JavaScript - Painting - 2Dグラフィックエンジン、ピクセル描画など 私が解説出来るほど収めておらず次の本をオススメします。 Webフロントエンド ハイパフォーマンス チューニング (著:久保田 光則)にて詳しく解説されています。 ここでも開発者ツールのパフォーマンスタブを利用した 「推測するな、計測せよ」という思想について触れられています。