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
    (発表時の内容に加筆修正済み)

    View Slide

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

    View Slide

  3. パクツイ
    登壇しろという圧を感じていたところに
    都合よく依頼が飛んできたので便乗

    View Slide

  4. © 2022 New Relic, Inc. All rights reserved
    New Relic の
    導入と実演

    View Slide

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

    View Slide

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

    View Slide

  7. © 2022 New Relic, Inc. All rights reserved.
    題材とする Laravel アプリの簡単な紹介
    バックエンドのテーブル構成

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  12. © 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 を使っているため若干異なります )

    View Slide

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

    View Slide

  14. © 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 リクエストを定期的に
    飛ばして死活監視

    View Slide

  15. © 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 アプリケーションの場合は無視できる程度

    View Slide

  16. © 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 がフロントエンドを監視する仕組み

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  20. © 2022 New Relic, Inc. All rights reserved
    大量レコードの
    読み込み

    View Slide

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

    View Slide

  22. © 2022 New Relic, Inc. All rights reserved.
    大量レコードの読み込み
    Eloquent Model のリレーションシップ定義

    View Slide

  23. © 2022 New Relic, Inc. All rights reserved.
    大量レコードの読み込み
    Eloquent Model のカスタム属性定義
    親に依存 祖先に依存

    View Slide

  24. © 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
    大量レコードの読み込み
    コントローラ

    View Slide

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

    View Slide

  26. © 2022 New Relic, Inc. All rights reserved.
    実演タイム
    (時間が無ければカット)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. © 2022 New Relic, Inc. All rights reserved.
    大量レコードの読み込み
    Cities, Districts, Parent を Eager Load した場合の結果 (APM) Prefecture
    City
    City
    District
    District

    View Slide

  31. © 2022 New Relic, Inc. All rights reserved.
    大量レコードの読み込み
    実際のところは…
    ループ処理中での Lazy Loading を
    検知して例外をスローしてくれる

    View Slide

  32. © 2022 New Relic, Inc. All rights reserved
    大量レコードの更新

    View Slide

  33. © 2022 New Relic, Inc. All rights reserved.
    New Relic を使った Laravel アプリの改善
    仕様のおさらい
    ● フロントエンドから 27 種類のフィールドが自治体の数だけあり,
    合計 50000 以上のフィールドが送られる
    ● 受け取った JSON を編集してそのまま送り返している

    prefectures, cities, districts がネストしている
    大量レコードの更新

    View Slide

  34. © 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, …)

    View Slide

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

    View Slide

  36. © 2022 New Relic, Inc. All rights reserved.
    大量レコードの更新
    バリデーションルールの定義(省略なし)

    View Slide

  37. © 2022 New Relic, Inc. All rights reserved.
    実演タイム
    (時間が無ければカット)

    View Slide

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

    View Slide

  39. © 2022 New Relic, Inc. All rights reserved.
    なんでそんなに重いの?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  50. © 2022 New Relic, Inc. All rights reserved.
    すべて自前で書く場合

    View Slide

  51. © 2022 New Relic, Inc. All rights reserved.
    すべて自前で書く場合

    View Slide

  52. © 2022 New Relic, Inc. All rights reserved.
    すべて自前で書く場合

    View Slide

  53. © 2022 New Relic, Inc. All rights reserved.
    ワイルドカード→配列インデックスの置換処理だけ自前で書く場合
    $i, $j, $k, …
    かんたん ♫

    View Slide

  54. © 2022 New Relic, Inc. All rights reserved.
    実演タイム
    (時間が無ければカット)

    View Slide

  55. © 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 をバリデーションした場合 …
    とっさの改修には
    意外と耐えられるかも!

    View Slide

  56. © 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倍ぐらいに

    View Slide

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

    View Slide

  58. © 2022 New Relic, Inc. All rights reserved
    まとめ

    View Slide

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

    View Slide

  60. © 2022 New Relic, Inc. All rights reserved
    1ユーザー &月間100GB の転送量までなら無料
    https://newrelic.com/signup

    View Slide

  61. © 2022 New Relic, Inc. All rights reserved
    Full-Stack Observability テスト開講❗❗
    https://learn.newrelic.com/full-stack-observability-exam-jp

    View Slide