Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

負荷試験の観点から見るGraphQLにおけるPHPのコードチューニング

 負荷試験の観点から見るGraphQLにおけるPHPのコードチューニング

PHPerKaigi2021
「負荷試験の観点から見るGraphQLにおけるPHPのコードチューニング」
2021/3/27(土) 12:30~ TrackA
https://fortee.jp/phperkaigi-2021/proposal/e544480b-4c90-4a42-8267-995f00544ae6

akkino/D-En

March 27, 2021
Tweet

More Decks by akkino/D-En

Other Decks in Programming

Transcript

  1. You can also split your content 自己紹介 3 遠藤 大輔

    Daisuke Endo • 2019年, 株式会社ゆめみに入社 • 趣味:ドラム, コンガ演奏 • Twitter: @DddEndow
  2. You can also split your content 会社紹介 4 • 世界中で5000万ユーザー/月

    • 給与自己決定, 有給取り放題 • GROW with YUMEMI みんなが知ってるあのサービス、 実はゆめみが作ってます。
  3. You can also split your content はじめに 8 GraphQL •

    リクエストまとめてスループットを向上 • 欲しいデータを欲しいだけ、効率よく取得 • エンドポイントの削減 → シンプルなデータ連携を実現
  4. You can also split your content はじめに 9 • でも実際GraphQLの性能ってどうなの?

    • 想定してた性能が出なくて炎上したら困る • 性能的な知見が少なくて足踏みしてる
  5. You can also split your content はじめに 10 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  6. 技術スタック • PHP 7.4 • Laravel 8 • Lighthouse 4.13

    • Locust 0.13 You can also split your content 動作環境 11
  7. You can also split your content アジェンダ 13 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  8. 結果 ※完全に同じデータを取得しているわけではないので多少ばらつきがある You can also split your content どれぐらいの性能が出たのか 15

    対象 応答時間 LaravelのIndexページ 約15ms GraphQL(単体のクエリ) 40ms ~ 100ms GraphQL(複数のクエリ) 50ms ~ 300ms REST API単体 30ms ~ 60ms
  9. 結果 ※完全に同じデータを取得しているわけではないので多少ばらつきがある You can also split your content どれぐらいの性能が出たのか 16

    対象 応答時間 LaravelのIndexページ 約15ms GraphQL(単体のクエリ) 40ms ~ 100ms GraphQL(複数のクエリ) 50ms ~ 300ms REST API単体 30ms ~ 60ms 意外と悪くなさそう ばらつきが大きい
  10. You can also split your content アジェンダ 18 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  11. You can also split your content RESTとの違い 21 10ms 10ms

    10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms REST GraphQL 90ms 50ms レイテンシ総量 Down↓
  12. You can also split your content RESTとの違い 22 10ms 10ms

    10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms REST GraphQL 90ms 50ms 33.3rps 20rps 1000ms / 30ms = 1000ms / 50ms =
  13. You can also split your content RESTとの違い 23 10ms 10ms

    10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms REST GraphQL 90ms 50ms 33.3rps 20rps 1000ms / 30ms = 1000ms / 50ms = 実際よりもスループットが 低く見えてしまう
  14. You can also split your content RESTとの違い 24 対策 •

    1リクエストあたりのクエリの数 x rpsで計算する • そういうものとして計算する → これといった答えはない (自分は後者を選択)
  15. You can also split your content 負荷のかかり方 25 負荷のかかり方 •

    単位時間あたりの処理量と負荷 • 並列処理の可否
  16. You can also split your content 負荷のかかり方 26 単位時間あたりの処理量と負荷 10ms

    10ms 10ms 10ms 10ms 50ms • より短い時間に処理が集中する ◦ → リソースへの負荷が高まる ◦ RPSは下がるのにCPU負荷が上がる
  17. You can also split your content 負荷のかかり方 27 1つのプロセスで処理をする •

    全ての処理が完了するまでメモリが解放されない → 必要なメモリ量の増加 10ms 10ms 10ms 10ms 10ms 1プロセス ここでメモリ解放
  18. You can also split your content 負荷のかかり方 28 全てのクエリが終わらないとレスポンスできない •

    遅いクエリが混ざっているとひきづられる • 1リクエストにクエリを含めすぎると遅くなる 10ms 10ms 10ms 10ms 10ms 40ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms
  19. You can also split your content 負荷のかかり方 31 対策 •

    実装 ◦ ペジネーション ◦ 複雑度の上限を設ける ◦ 分割ロード(deferディレクティブ) • その他 ◦ 応答速度が長くても問題ない性能要件 ◦ フロント側の実装
  20. You can also split your content アジェンダ 32 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  21. You can also split your content コードチューニングの勘所 34 • OPCacheは必須

    • 必要なカラムのみ取得 • N+1問題対策 • whereInとwhereHasの使い分け
  22. You can also split your content コードチューニングの勘所 35 OPCache •

    PHPアクセラレータ ◦ コンパイル済みのPHPコードを共有メモリに保存し、パフォーマンス を向上させる • Lighthouse(GraphQLライブラリ)にも対応 • 入れるだけで200ms→30msになる
  23. You can also split your content コードチューニングの勘所 37 必要なカラムのみ取得(対策なし) 1.nameとpostsのみを

    取得するクエリを実行 2.不必要なクエリまで発行されてしまう(diaries, friends)
  24. You can also split your content コードチューニングの勘所 38 必要なカラムのみ取得 •

    リクエストされたクエリを確認し、必要なSQLのみ実行する実 装が必要 • GraphQLでは1:n, n:nの関係が多くなる ◦ Joinなどで分解できないクエリにすると負荷が高まる 遅延ロードやサブクエリで対策 (Lighthouseならデフォルトで対応)
  25. You can also split your content コードチューニングの勘所 41 WhereInとWhereHasの使い分け •

    GraphQLの仕組み上サブクエリを使うことが多い ◦ 1:n, n:nの関係が多い ◦ データ構造のネスト → 不用意に相関サブクエリを使用すると性能が劣化
  26. You can also split your content コードチューニングの勘所 42 WhereInとWhereHasの使い分け •

    親クエリがテーブル全体を参照するならWhereIn • 親クエリである程度絞れるならWhereHas データに応じて使い分けることが重要
  27. You can also split your content まとめ 44 まとめ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  28. You can also split your content まとめ 45 • OPCache設定すればプロダクトでも問題なく使える

    • 軽くて大量のリクエストがあるなら高速化が見込める • チューニングで意識するポイントはRESTとあまり変わらない • 処理の重いクエリはRESTを使うか、別の言語を使う