Upgrade to Pro — share decks privately, control downloads, hide ads and more …

推測するな、計測せよ New Relic × Laravel 実践

mpyw
March 24, 2023

推測するな、計測せよ New Relic × Laravel 実践

PHPerKaigi 2023 Day1 スポンサーセッション
New Relic 株式会社所属の大平譲さん (Joe さん) との共同登壇です。

・権利の関係上,一部スライドを削除しております。
・逆に時間の都合で,発表ではスキップしたスライドが含まれている部分があります。
・NewRelic さんのスライドテーマをそのまま拝借している都合で, Speaker Deck に上げたときに太字のフォントが白抜きになって割れている部分があります。体裁はあまり気にせずにご覧ください。

AWS Fargate とのクロック相性によるパフォーマンスデグレーションの対策に関しては,カジュアルにアプリケーションをデプロイしたい PHPer からしたら一番欲しいところですよね!是非とも声を上げた上で,今後に期待しましょう…

mpyw-yattemita/phperkaigi2023-laravel-newrelic-performance: PHPerKaigi 2023 向け: Laravel × New Relic でパフォーマンス計測例
https://github.com/mpyw-yattemita/phperkaigi2023-laravel-newrelic-performance

mpyw

March 24, 2023
Tweet

More Decks by mpyw

Other Decks in Programming

Transcript

  1. © 2022 New Relic, Inc. All rights reserved 推測するな、計測せよ New

    Relic × Laravel 実践 Yuzuru Ohira & mpyw PHPerKaigi 2023 Day1 (発表時の内容に加筆修正済み)
  2. © 2022 New Relic, Inc. All rights reserved 自己紹介 Joe

    氏とは以前の職場での知り合い。 最近 PHP を書く機会が激減して少し寂しくなっている… @mpyw PHPerKaigi 初登壇です!
  3. © 2022 New Relic, Inc. All rights reserved New Relic

    の導入と実演 Ⅰ 題材とする Laravel アプリの簡単な紹介 Ⅱ New Relic Agent を Laravel アプリに導入 Ⅲ New Relic APM の基本的な仕組み Ⅳ New Relic を使った Laravel アプリの改善
  4. © 2022 New Relic, Inc. All rights reserved. 題材とする Laravel

    アプリの簡単な紹介 • 総務省が提供する Excel 統計データを整形して使用 • 項目 ◦ 全人口, 男性人口, 女性人口, 人口密度, 若年層人口, 高齢者人口, etc… ◦ 計 27 項目 • 自治体 ◦ Prefectures (都道府県 + 全国): 48 ◦ Cities (市町村 + 東京23区): 1742 ◦ Districts (区): 175 大量の人口統計を表示・編集するアプリ 27 × (48+1742+175) = 53055 個
  5. © 2022 New Relic, Inc. All rights reserved. 題材とする Laravel

    アプリの簡単な紹介 バックエンドのテーブル構成
  6. © 2022 New Relic, Inc. All rights reserved. クリックすると 展開表示

    遅延表示しているだけ 遅延取得はしていない これらを一気に表示・送信する巨大フォーム
  7. © 2022 New Relic, Inc. All rights reserved. 題材とする Laravel

    アプリの簡単な紹介 • (読込)Eager Loading, Lazy Loading の切り替え • (更新)Validator の切り替え (デモの都合上)バックエンドの動作を切り替える機能を搭載
  8. © 2022 New Relic, Inc. All rights reserved New Relic

    の導入と実演 Ⅰ 題材とする Laravel アプリの簡単な紹介 Ⅱ New Relic Agent を Laravel アプリに導入 Ⅲ New Relic APM の基本的な仕組み Ⅳ New Relic を使った Laravel アプリの改善
  9. © 2022 New Relic, Inc. All rights reserved. New Relic

    Agent を Laravel アプリに導入 • ガイドインストール機能! (初心者はとりあえずこれで) • PHPer の方はだいたい APM → PHP → Docker を 選んでおけばいいと思います • 時間の都合上ポチポチする部分は省略 具体的な導入手順 https://github.com/mpyw-yattemita/phperkaigi2023-laravel-newrelic-performance 少しアレンジして整備した見本 ↓
  10. © 2022 New Relic, Inc. All rights reserved. New Relic

    Agent を Laravel アプリに導入 • PHP Agent ◦ PHP Extension として関数の 呼び出しなどをトラッキング ◦ フレームワークごとの特殊対応も • PHP Daemon ◦ PHP Agent が収集したデータを New Relic に転送する • Infrastructure ◦ リソースの使用状況などを New Relic に転送する ◦ 直インストールまたは 特権を付与されたコンテナ 一般的なコンテナ構成 (今回は Kubernetes を使っているため若干異なります )
  11. © 2022 New Relic, Inc. All rights reserved New Relic

    の導入と実演 Ⅰ 題材とする Laravel アプリの簡単な紹介 Ⅱ New Relic Agent を Laravel アプリに導入 Ⅲ New Relic APM の基本的な仕組み Ⅳ New Relic を使った Laravel アプリの改善
  12. © 2022 New Relic, Inc. All rights reserved. New Relic

    APM の基本的な仕組み • APM ◦ バックエンドアプリのパフォーマンス分析 ◦ 1 回のリクエストのトレースなどを トランザクションという単位で計測 ◦ PHP Extension ゆえに自動記録可能! • Distributed Tracing ◦ ある 1 回のトランザクションの間に, マイクロサービス間で発生したやり取りを すべて連結して記録できる ◦ フロントエンドの Web ブラウザ上での 動きも含めて記録できる ◦ APM で異常検知されなかった (サンプリングされた)正常系も確認できる New Relic の主要機能 • Logs ◦ JSONL 形式でのログの記録と検索 ◦ Logs in Context という機能を使うと トランザクションに紐付けできる ◦ PHP Extension ゆえに自動紐付け可能! • Infrastructure ◦ CPU やメモリなどのリソースの 使用状況を監視できる • Synthetic Monitoring ◦ HTTP リクエストを定期的に 飛ばして死活監視
  13. © 2022 New Relic, Inc. All rights reserved. AWS Fargate

    では 大幅性能劣化 ( CPU クロックの相性が悪い ) 8.2 ( 収録時まで 8.1 でしたが,   完了後に対応されました 🎉) 8.x (公式サポートはされていないが概 ね 9.x, 10.x でも動きそう) 自動記録の制約 対応 PHP バージョン 対応 Laravel バージョン PHP × New Relic は自動記録できて便利 …だが? ちょっと惜しいポイントが … EC2 ベースの ECS/EKS を使う💡 手動記録する 🥺 自動記録の対象関数を限定 💡 ← newrelic.transaction_tracer.detail = 0 ← newrelic.transaction_tracer.custom = Foo::x,Bar::y ← Fargate よりはマシというだけで,依然として多少のオーバーヘッドはある IO 遅延がメインの PHP アプリケーションの場合は無視できる程度
  14. © 2022 New Relic, Inc. All rights reserved. New Relic

    APM の基本的な仕組み • バックエンドからの JavaScript スクリプト注入 ◦ PHP Agent が HTML を返却する際, PHP 標準機能にある output_handler を 使って注入している ◦ Extension をインストールしていれば 自動的に New Relic の Output Handler が 登録される • フロントエンドから New Relic に直接通信 ◦ デベロッパーツールで通信している 様子を確認できる (参考) Distributed Tracing がフロントエンドを監視する仕組み
  15. © 2022 New Relic, Inc. All rights reserved. New Relic

    APM の実際の画面を確認 時間のかかったトランザクション Laravel デフォルトでは コントローラ名@メソッド がタイトル
  16. © 2022 New Relic, Inc. All rights reserved. New Relic

    APM の実際の画面を確認 時間のかかった SQL ・ テーブル名と操作の種類 ・ どのトランザクションから呼び出されているか ・ (スロークエリ判定された場合)具体的なクエリの内容
  17. © 2022 New Relic, Inc. All rights reserved New Relic

    の導入と実演 Ⅰ 題材とする Laravel アプリの簡単な紹介 Ⅱ New Relic Agent を Laravel アプリに導入 Ⅲ New Relic APM の基本的な仕組み Ⅳ New Relic を使った Laravel アプリの改善
  18. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 バックエンドのテーブル構成(再掲) 大量レコードの読み込み
  19. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み Eloquent

    Model のカスタム属性定義 親に依存 祖先に依存
  20. © 2022 New Relic, Inc. All rights reserved. • 子要素の

    Eager Loading 設定の分岐 ◦ Eager Loading なし ◦ Cities のみ Eager Loading ◦ Cities, Districts ともに Eager Loading • 親要素の Eager Loading 設定の分岐 ◦ Eager Loading なし ◦ City, Prefecture ともに Eager Loading 大量レコードの読み込み コントローラ
  21. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み HTTP

    Resource の toArray() の実装 • 子要素の Lazy Loading 設定の分岐 ◦ Lazy Loading しない ◦ Cities のみ Lazy Loading ◦ Cities, Districts ともに Lazy Loading whenLoaded() は Eager Loading されている場合のみ表示する機能
  22. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み Cities,

    Districts を Lazy Load した場合の結果 (APM) N+1 がとんでもないことに! Prefecture City City District District
  23. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み Cities,

    Districts を Eager Load した場合の結果 (APM) 親に依存している疑似属性での Lazy Loading がボトルネックに Prefecture City City District District
  24. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み Cities,

    Districts を Eager Load した場合の結果 (Distributed Tracing) リソース → レスポンスの変換で 時間がかかっているのが分かる
  25. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み Cities,

    Districts, Parent を Eager Load した場合の結果 (APM) Prefecture City City District District
  26. © 2022 New Relic, Inc. All rights reserved. 大量レコードの読み込み 実際のところは…

    ループ処理中での Lazy Loading を 検知して例外をスローしてくれる
  27. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 仕様のおさらい • フロントエンドから 27 種類のフィールドが自治体の数だけあり, 合計 50000 以上のフィールドが送られる • 受け取った JSON を編集してそのまま送り返している ↓ prefectures, cities, districts がネストしている 大量レコードの更新
  28. © 2022 New Relic, Inc. All rights reserved. 大量レコードの更新 種類ごとに

    1000 件溜まったらバルクアップデートするコード UPDATE SET x = ELT(FIELD(id, 1, 2, 3, …), ‘a’, ‘b’, ‘c’, …) WHERE id IN (1, 2, 3, …)
  29. © 2022 New Relic, Inc. All rights reserved. 大量レコードの更新 バリデーションルールの定義(省略あり)

    ワイルドカードでネストした配列の 子要素を指定する機能がある • CPU 演算で完結するシンプルなルール群 • データベースアクセスしないルールのみ
  30. © 2022 New Relic, Inc. All rights reserved. 大量レコードの更新 ネストした

    Cities, Districts を Laravel の通常の Validator で更新した場合の結果 (APM) Validator のワイルドカードルール関連が激重 タイムアウトして データベースにアクセスするところまで たどり着いていない…
  31. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 送られてくるデータは 立体構造やな
  32. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 でもルールは 宣言的にこう書きたい
  33. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 データ側をいったん フラットしにしてみよう
  34. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 完全フラットやと途中階層の バリデーションが出来ひんな
  35. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 ルールに対応するところは 途中階層の配列も用意せな
  36. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 ヨシッ! あとはルール側の * をデー タの分だけ 複製すればいいわ!
  37. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Laravel の Validator が重い理由 大量レコードの更新 できた!
  38. © 2022 New Relic, Inc. All rights reserved. 変換されたルール 変換されたデータ

    ルールとデータが1対1対応! シンプルになった✌ 今からループ回すで!
  39. © 2022 New Relic, Inc. All rights reserved. 変換されたルール 変換されたデータ

    ルールとデータが1対1対応! シンプルになった✌ 今からループ回すで! そりゃ重いやろ
  40. © 2022 New Relic, Inc. All rights reserved. New Relic

    を使った Laravel アプリの改善 Validator が重すぎるのでなんとかする • Laravel の Validator を使わずに自分で何とかする ◦ 理論上最速だがやや書くのが大変 • 「ワイルドカード → 配列インデックス」の置換処理を Laravel に任せずに自前でやる ◦ 効果あるか怪しいが …簡単! 大量レコードの 更新 バリデーション
  41. © 2022 New Relic, Inc. All rights reserved. タイムアウト 1秒

    NewRelic なし: 8〜15秒 New Relic あり: 15〜30秒 Laravel Validator Pure PHP Validator Wildcard-less Laravel Validator 大量レコードのバリデーション ネストした Cities, Districts をバリデーションした場合 … とっさの改修には 意外と耐えられるかも!
  42. © 2022 New Relic, Inc. All rights reserved. (参考) Laravel

    8.x までと Laravel 9.x からの違い Validator::$excludeUnvalidatedArrayKeys array 要素からバリデーション対象外のキーを排除 • Laravel 8.x まで false がデフォルト • Laravel 9.x から true がデフォルト 実行時間が 2倍ぐらいに
  43. © 2022 New Relic, Inc. All rights reserved. 大量レコードのバリデーション 実際のところは…

    • ワイルドカードルールがネストしまくりのフォーム設計は可能な限りやめましょう • どうしても避けられないときは … ◦ 要素数を Laravel のバリデータを使わずに 現実的な数までに制限しましょう ◦ 制限してもなお無視できない量がある場合は,ワイルドカードルールに代わる 解決策を考えましょう
  44. © 2022 New Relic, Inc. All rights reserved. まとめ •

    New Relic には便利な機能がいっぱい! ◦ APM, Distributed Tracing, Logs in Context には特にお世話になることが多そう • 推測するな,計測せよ ◦ PHP でも IO がボトルネックとは限らない ◦ 有名 OSS の中にも恐ろしく非効率なコードが紛れていることがある
  45. © 2022 New Relic, Inc. All rights reserved 1ユーザー &月間100GB

    の転送量までなら無料 https://newrelic.com/signup
  46. © 2022 New Relic, Inc. All rights reserved Full-Stack Observability

    テスト開講❗❗ https://learn.newrelic.com/full-stack-observability-exam-jp