Laravel Jp Conferenceの資料です。
どのようにウェブアプリケーションのパフォーマンスチューニングを考えていくのか、基本をまとめました。
Laravelで学ぶWebアプリケーションチューニングの基本Laravel Jp Conference 2019/02/16
View Slide
自己紹介名前 : 富所 亮 | Ryo Tomidokoro職業 : Web Application Engineer職歴 : SIer > 事業会社 > 受託 > 受託所属 : Innovator Japan Inc.主な出現場所 : PHP界隈の各種勉強会
諸注意スライドはSpeakerDeckにアップ済みです。写真はご自由に。でも周りに気をつけて…
はじめに
本トークの内容自分がいつもやっていることをまとめました現場や個人開発でやったこと、本で読んで学んだことがベースになっています
いきなりですが質問です
パフォーマンスチューニングしたことありますか?
経験者の方へご自身のやり方と比べて見てください改善のヒントになったら幸いです
未経験者の方へチューニングは職人芸ではないやることが分かれば怖くない
本トークの目指すところ特にチューニングの経験が浅い方にとってまず何をどうしてよいか分からない!?という状態を解消することに重点を置いています。
基本的なことを再確認することでパフォーマンスチューニングでやるべきことが明確になることを期待しています。
ついでにLaravelが持つ基本的な機能がどのようなケースで役立つのかを紹介します必要十分な機能がすでに備わっています
アウトライン1. 全体を見る2. パフォーマンスを科学する3. ウェブアプリの責任?4. サーバーメトリクスを確認する5. ウェブアプリの処理を特定する6. プロファイリングする7. 改善ループを回す8. よくある問題処理とその対処
1. 全体を見る2. パフォーマンスを科学する3. ウェブアプリの責任?4. サーバーメトリクスを確認する5. ウェブアプリの処理を特定する6. プロファイリングする7. 改善ループを回す8. よくある問題処理とその対処
1. 全体を見る
遅いとは?とても曖昧な言葉。私の「遅い」とあなたの「遅い」は比較出来ない「遅い」は主観、個人差がある。
曖昧な意見「うちのウェブアプリケーション遅くない?」
問題を提起しているように見えて何もかもが曖昧で分からないこのような「遅い」では改善が行えない。
具体的な意見「弊社のウェブアプリは 平日18:00〜19:00の時間帯で 通常よりも500msec応答速度が遅い」
コンテキストや数値が説明されることで、具体的な状況が浮彫になってくるこういう「遅い」は改善につながる
まず、曖昧な「遅い」を数値で表せる「遅い」に変換する必要があります。「推測するな計測せよ」の世界です。
状況が分かったとして、何が原因で「遅い」発生しているかは分かりません。原因究明のために、ウェブアプリに関わる全体をみる必要があります。
ウェブアプリケーションはどのようにしてブラウザに表示されるのか?
ウェブアプリケーションの全体像ネットワークはなぜつながるのか? - 戸根勤(日経BP社) P10
自分の領域の狭さを知るLaravel
アンコントローラブルな領域ウェブアプリだけでは改善できない領域が沢山あるそもそもウェブアプリが「遅い」の原因なのかも分からない
遅いの原因をつきとめるなんとなくアタリをつけてはいけないエンジニアとして科学的に突き止める必要があるが‥どうする?
2. パフォーマンスを科学する
「遅い」の考え方
レイテンシー任意の状態から、任意の状態まで待つためにかかった時間を計測した値例)HTTPのリクエストからレスポンスまでDBのクエリ送信からデータ受信まで詳解システム・パフォーマンス Brendan Gregg 西脇靖紘 長尾高弘(オライリー・ジャパン)
ウェブアプリ全体のレイテンシーユーザー側ネットワークプロバイダプロバイダ光ファイバー等サーバー側ネットワーク
レイテンシーの中身をみて、ウェブアプリ単体のレスポンスタイムがボトルネックで無い場合ウェブアプリ以外で対処する方が効率が良い
例えば大陸間のネットワーク通信速度制限のかかった格安SIM共有LAN内の輻輳ウェブアプリ以外の遅さ
EC2で試してみる
Tokyo vs USATokyo RegionUbuntu 16.06 LTSN. Virginia RegionUbuntu 16.06 LTS
東京のブラウザからアクセスTokyoN. Virginia
大陸間の移動でかかる時間アメリカ大陸まで +200msecウェブアプリケーションでは改善できない!CDN等のソリューションが必要
3. ウェブアプリの責任?
全体のレイテンシーの中でサーバー側ネットワークの占める割合が大きい場合ウェブアプリをチューニングすることで得られる可能性が高いユーザー側ネットワークプロバイダプロバイダ光ファイバー等サーバー側ネットワーク
レイテンシーにおけるウェブアプリ単体の占める時間は、ウェブサーバーが記録する「レスポンスタイム」で知ることが出来る
レスポンスタイム各ウェブサーバーはログにレスポンスタイムを出力することが出来る。Apache : %DNginx : $request_timeH2O : duration
ウェブアプリ単体のレイテンシーサーバー側ネットワークウェブサーバーのレスポンスタイム その他通信
ウェブアプリ全体のレイテンシーを確認して、ウェブアプリ単体の応答時間に原因があると分かって、はじめてウェブアプリのチューニングを開始できる。
しかし、ウェブアプリ単体のレスポンスが悪かったとして、本当にウェブアプリが悪いのでしょうか?その「遅さ」はウェブアプリの責任?
4. サーバーメトリクスを見る
ウェブアプリ以外の原因同一サーバー上で動く他のプロセスがリソースを消費しているケースがある例)誰かが閉じ忘れたemacsのプロセスが100%で張り付いてた…とか
原因を探るための指標メモリ使用量、CPU使用率、ディスクIO、ネットワークIO etc…継続的な測定が基本。中長期の傾向値が無いと判断がしづらい
測定ツールsysstatパッケージホスティングが提供するツール (CloudWatch)SaaSの監視ツール (Mackerel)インストール型の測定ツール (netdata)
sysstatパッケージsar, pidstat, dstat ...
Mackerel
netdata
ボトルネックを特定するこの段階では、プロセス単位でのCPU使用率、メモリ使用量などから、どのプロセスがボトルネックになっているのかを特定一個ずつ一個ずつ、原因を絞り込んでいく
ついにウェブアプリが原因らしいということが分かったじゃあ、次は何をしたらいい?
5. ウェブアプリの処理を特定する
ウェブアプリのどの処理が原因なのか?どうやったら分かるのか?この段階では「PHPのプログラムが原因らしい」としか分かっていない。
レスポンスタイムから探すウェブサーバーのログから、レスポンスタイムが遅いURLを探すawk, alp, kataribe等を使って簡単に解析できる
alpの例
ウェブ系ツールを頼る自分はNew Relicしか使ったことないのですが、簡単にボトルネックのURLや処理を特定することができます。
New Relicの例
6. プロファイリングする
プロファイリング?コード実行時にどの処理にどのくらいの時間がかかっているのかを計測したものと、言葉で言われてもピンとこないので実例を見たほうが早い
blackfire.ioの例
その他のツールXdebugXhproftideways他にもありそうです…
処理が特定できて、プロファイラーの結果が取得できたら、チューニングの準備がようやく整ったことになるここから、ウェブアプリ単体のレイテンシーについて考えていく段階になる
7. 改善ループを回す
ウェブアプリ単体のレイテンシーレスポンス出力APIコールRouting DBクエリーLibrary読込例)
この先は、レイテンシーの中でボトルネックになっている処理をチューニングしていくこの先は1. レイテンシー確認2. ボトルネック改善3. レイテンシー確認...を延々と繰り返す
改善ループ1
理論上400msec程度のパフォーマンス改善が見込める→仮に上手に改善できたとすると…
改善ループ2
ボトルネックが他の処理に移ったことがわかるここも改善することでさらに200msec→上手く改善すると...
改善ループ3
処理の特定さえ出来てしまえば、あとはTry&Errorを繰り返すことでチューニングは達成することが出来る。処理の特定はプロファイラがやってくれる
8. よくある問題とその対処
この先は、個別の象徴的なケースを例にとって、その対処法を説明します。→Laravelにちょうどよい解決法があるものは[L]マークがついています!
HTTPのAPIコール一回のリクエストで複数APIをコールするようになると、途端に処理が遅くなる→更新頻度によってはCache [L]→自前APIであれば、専用APIにまとめてコール回数を減らす→フロントのJSに移譲する
メール送信SMTPとの通信は体感1secくらいかかる。複数メール送信がリクエストに同期的に書いてあると絶望的に遅い→Queue [L]
Slack通知これもメール送信と同じ。同期的な処理にしているとびっくりするほど遅くなります。→Queue [L]
SQLクエリー実行@soudai1025 のスライド見れば多分解決…単発のクエリーが遅い場合は適切なDB設計と、インデックス設計が効きます。→SELECTであればCacheという手もあります。あまりオススメしませんが…[L]
リスト形式の表示で問題になるやつです。Laravelのrelationをbladeから呼び出すと、カジュアルに大量のクエリを発生させられます。→eager loading [L]N+1クエリ
入れ子のLoopとか、1万件とかのforeachとか、常識を外れた蛮行によるもの…Laravel Collectionの乱用なども…→レビューや内部勉強会で防ぐしかない…計算量が無駄に多いプログラム
こちらにも詳しく書きましたhttps://speakerdeck.com/hanhan1978/laravel-collectionfalseji-suan-liang-wodiao-betemita
色々、見てきましたが処理の遅いプログラムのチューニング方法は対処方法が2つくらいしか無い。・アルゴリズムの変更・非同期化
チューニングとは、全体を見ながら少しずつ少しずつ原因を特定していくプロセスです。泥臭く追い込んでいく一連の作業をやってみると、ウェブアプリの理解がさらに深まります。最後に…
参考資料詳解システム・パフォーマンスBrendan Gregg 西脇靖紘 長尾高弘オライリー・ジャパンネットワークはなぜつながるのか?戸根勤日経BP社サーバー・インフラを支える技術伊藤 直也, 勝見 祐己, 田中 慎司, ひろせ まさあき, 安井 真伸, 横川 和哉WEB+DB PRESS plus