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を使うか、別の言語を使う