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

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

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

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

94dac49f3455009e22b372ab8cd60182?s=128

akkino/D-En

March 27, 2021
Tweet

Transcript

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

  2. 1. 自己紹介 & 会社紹介 Self & Company introduction 2

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

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

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

  6. 1. はじめに Introduction 6

  7. You can also split your content You can also split

    your content 7
  8. You can also split your content はじめに 8 GraphQL •

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

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

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

    • Locust 0.13 You can also split your content 動作環境 11
  12. You can also split your content 動作環境 12

  13. You can also split your content アジェンダ 13 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  14. 2. どれぐらいの性能が出たのか Result 14

  15. 結果 ※完全に同じデータを取得しているわけではないので多少ばらつきがある You can also split your content どれぐらいの性能が出たのか 15

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

    対象 応答時間 LaravelのIndexページ 約15ms GraphQL(単体のクエリ) 40ms ~ 100ms GraphQL(複数のクエリ) 50ms ~ 300ms REST API単体 30ms ~ 60ms 意外と悪くなさそう ばらつきが大きい
  17. 全然使えそうだけど... • GraphQL用フレームワークの処理で約10~20ms遅くなる • クエリの内容によっては大きな差が発生する You can also split your

    content どれぐらいの性能が出たのか 17 これについて解説
  18. You can also split your content アジェンダ 18 アジェンダ •

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  19. 3. RESTと異なるポイント&負荷のかかり方 Difference from REST 19

  20. You can also split your content RESTとの違い 20 GraphQLのリクエスト方法 リクエスト

    クエリ クエリ クエリ
  21. 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↓
  22. 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 =
  23. 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 = 実際よりもスループットが 低く見えてしまう
  24. You can also split your content RESTとの違い 24 対策 •

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

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

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

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

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

    10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms
  30. You can also split your content 負荷のかかり方 30 並列処理の可否 →PHPでは並列処理はできない

    10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms
  31. You can also split your content 負荷のかかり方 31 対策 •

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

    実際にどれぐらいの性能が出たのか • RESTと異なるポイント&負荷のかかり方 • コードチューニングの勘所
  33. 4. コードチューニングの勘所 Code Tuning 33

  34. You can also split your content コードチューニングの勘所 34 • OPCacheは必須

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

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

    取得するクエリを実行
  37. You can also split your content コードチューニングの勘所 37 必要なカラムのみ取得(対策なし) 1.nameとpostsのみを

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

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

    posts取得クエリが発行される
  40. You can also split your content コードチューニングの勘所 40 N+1問題対策 リレーションディレクティブやwithディレクティブ

    を用いて遅延ロードを実装する (自前実装でも可)
  41. You can also split your content コードチューニングの勘所 41 WhereInとWhereHasの使い分け •

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

    親クエリがテーブル全体を参照するならWhereIn • 親クエリである程度絞れるならWhereHas データに応じて使い分けることが重要
  43. 5. まとめ Session summary 43

  44. You can also split your content まとめ 44 まとめ •

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

    • 軽くて大量のリクエストがあるなら高速化が見込める • チューニングで意識するポイントはRESTとあまり変わらない • 処理の重いクエリはRESTを使うか、別の言語を使う
  46. “ GraphQLとRESTに性能的な差はない 要件・設計によって適切に使い分けることが重要 46

  47. Let’s Enjoy GraphQL for PHP. 47

  48. Thanks! YUMEMI.inc Daisuke Endo Twitter: @DddEndow 48