Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

You can also split your content 自己紹介 3 遠藤 大輔 Daisuke Endo ● 2019年, 株式会社ゆめみに入社 ● 趣味:ドラム, コンガ演奏 ● Twitter: @DddEndow

Slide 4

Slide 4 text

You can also split your content 会社紹介 4 ● 世界中で5000万ユーザー/月 ● 給与自己決定, 有給取り放題 ● GROW with YUMEMI みんなが知ってるあのサービス、 実はゆめみが作ってます。

Slide 5

Slide 5 text

You can also split your content 会社紹介 5

Slide 6

Slide 6 text

1. はじめに Introduction 6

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

You can also split your content はじめに 8 GraphQL ● リクエストまとめてスループットを向上 ● 欲しいデータを欲しいだけ、効率よく取得 ● エンドポイントの削減 → シンプルなデータ連携を実現

Slide 9

Slide 9 text

You can also split your content はじめに 9 ● でも実際GraphQLの性能ってどうなの? ● 想定してた性能が出なくて炎上したら困る ● 性能的な知見が少なくて足踏みしてる

Slide 10

Slide 10 text

You can also split your content はじめに 10 アジェンダ ● 実際にどれぐらいの性能が出たのか ● RESTと異なるポイント&負荷のかかり方 ● コードチューニングの勘所

Slide 11

Slide 11 text

技術スタック ● PHP 7.4 ● Laravel 8 ● Lighthouse 4.13 ● Locust 0.13 You can also split your content 動作環境 11

Slide 12

Slide 12 text

You can also split your content 動作環境 12

Slide 13

Slide 13 text

You can also split your content アジェンダ 13 アジェンダ ● 実際にどれぐらいの性能が出たのか ● RESTと異なるポイント&負荷のかかり方 ● コードチューニングの勘所

Slide 14

Slide 14 text

2. どれぐらいの性能が出たのか Result 14

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

全然使えそうだけど... ● GraphQL用フレームワークの処理で約10~20ms遅くなる ● クエリの内容によっては大きな差が発生する You can also split your content どれぐらいの性能が出たのか 17 これについて解説

Slide 18

Slide 18 text

You can also split your content アジェンダ 18 アジェンダ ● 実際にどれぐらいの性能が出たのか ● RESTと異なるポイント&負荷のかかり方 ● コードチューニングの勘所

Slide 19

Slide 19 text

3. RESTと異なるポイント&負荷のかかり方 Difference from REST 19

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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↓

Slide 22

Slide 22 text

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 =

Slide 23

Slide 23 text

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 = 実際よりもスループットが 低く見えてしまう

Slide 24

Slide 24 text

You can also split your content RESTとの違い 24 対策 ● 1リクエストあたりのクエリの数 x rpsで計算する ● そういうものとして計算する → これといった答えはない (自分は後者を選択)

Slide 25

Slide 25 text

You can also split your content 負荷のかかり方 25 負荷のかかり方 ● 単位時間あたりの処理量と負荷 ● 並列処理の可否

Slide 26

Slide 26 text

You can also split your content 負荷のかかり方 26 単位時間あたりの処理量と負荷 10ms 10ms 10ms 10ms 10ms 50ms ● より短い時間に処理が集中する ○ → リソースへの負荷が高まる ○ RPSは下がるのにCPU負荷が上がる

Slide 27

Slide 27 text

You can also split your content 負荷のかかり方 27 1つのプロセスで処理をする ● 全ての処理が完了するまでメモリが解放されない → 必要なメモリ量の増加 10ms 10ms 10ms 10ms 10ms 1プロセス ここでメモリ解放

Slide 28

Slide 28 text

You can also split your content 負荷のかかり方 28 全てのクエリが終わらないとレスポンスできない ● 遅いクエリが混ざっているとひきづられる ● 1リクエストにクエリを含めすぎると遅くなる 10ms 10ms 10ms 10ms 10ms 40ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms

Slide 29

Slide 29 text

You can also split your content 負荷のかかり方 29 並列処理の可否 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms 10ms

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

You can also split your content 負荷のかかり方 31 対策 ● 実装 ○ ペジネーション ○ 複雑度の上限を設ける ○ 分割ロード(deferディレクティブ) ● その他 ○ 応答速度が長くても問題ない性能要件 ○ フロント側の実装

Slide 32

Slide 32 text

You can also split your content アジェンダ 32 アジェンダ ● 実際にどれぐらいの性能が出たのか ● RESTと異なるポイント&負荷のかかり方 ● コードチューニングの勘所

Slide 33

Slide 33 text

4. コードチューニングの勘所 Code Tuning 33

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

You can also split your content コードチューニングの勘所 35 OPCache ● PHPアクセラレータ ○ コンパイル済みのPHPコードを共有メモリに保存し、パフォーマンス を向上させる ● Lighthouse(GraphQLライブラリ)にも対応 ● 入れるだけで200ms→30msになる

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

You can also split your content コードチューニングの勘所 39 N+1問題対策 無対策だとユーザーの数分 posts取得クエリが発行される

Slide 40

Slide 40 text

You can also split your content コードチューニングの勘所 40 N+1問題対策 リレーションディレクティブやwithディレクティブ を用いて遅延ロードを実装する (自前実装でも可)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

You can also split your content コードチューニングの勘所 42 WhereInとWhereHasの使い分け ● 親クエリがテーブル全体を参照するならWhereIn ● 親クエリである程度絞れるならWhereHas データに応じて使い分けることが重要

Slide 43

Slide 43 text

5. まとめ Session summary 43

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

You can also split your content まとめ 45 ● OPCache設定すればプロダクトでも問題なく使える ● 軽くて大量のリクエストがあるなら高速化が見込める ● チューニングで意識するポイントはRESTとあまり変わらない ● 処理の重いクエリはRESTを使うか、別の言語を使う

Slide 46

Slide 46 text

“ GraphQLとRESTに性能的な差はない 要件・設計によって適切に使い分けることが重要 46

Slide 47

Slide 47 text

Let’s Enjoy GraphQL for PHP. 47

Slide 48

Slide 48 text

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