システムの性能について話していると、よく出てくる言葉があります。
- Latency
- Throughput
どちらも「速さ」に関係する言葉なので、最初は少し混同しやすいです。
ただ、実際には見ているものが違います。
かなりざっくり言うと、
Latency = 1回の処理にどれくらい時間がかかるか
Throughput = 一定時間にどれくらい処理できるか
です。
この2つを分けて考えられるようになると、性能改善の話もかなり整理しやすくなります。
Latencyとは
Latencyは、ある処理を開始してから結果が返ってくるまでに、どれくらい時間がかかるかを表します。
たとえばAPIなら、次の流れがあります。
Request -> Server -> Response
このRequestを送ってからResponseが返ってくるまでの時間がLatencyです。
たとえば、
GET /users/1
Latency: 100ms
だった場合、そのAPIはだいたい100msでレスポンスを返している、ということになります。
なのでLatencyは、
1回の処理でどれくらい待つか
と考えるとわかりやすいです。
Webアプリであれば、ユーザーがボタンを押してから画面に結果が出るまでの時間にも関係してきます。
Latencyが大きいと、それだけ「なんか遅いな」と感じやすくなります。
Throughputとは
一方でThroughputは、
一定時間にどれくらいの処理を完了できるか
を見る指標です。
たとえばAPIサーバーが1秒間に1,000リクエスト処理できるのであれば、
Throughput: 1,000 requests/sec
というイメージです。
API以外でも同じです。
メッセージ処理なら、
50,000 messages/sec
画像処理なら、
500 images/sec
のように表せます。
つまりThroughputは、
システム全体としてどれくらいの量を捌けるか
を見るものです。
LatencyとThroughputの違い
整理すると、違いはかなりシンプルです。
| 指標 | 見ているもの |
|---|---|
| Latency | 1つの処理にかかる時間 |
| Throughput | 一定時間に処理できる量 |
たとえば、あるAPIサーバーが、
Latency: 100ms
Throughput: 1,000 req/s
だったとします。
これは、
- 1回のリクエストはだいたい100msで返る
- システム全体では1秒間に約1,000件処理できる
という意味です。
どちらも性能の話ではありますが、見ている方向が違います。
Latencyが低ければThroughputも高いのか
ここは少しややこしいところです。
感覚的には、
1回の処理が速いなら、たくさん処理できるんじゃないの?
と思います。
もちろん、そうなることもあります。
ただし、
Latencyが低い = Throughputが高い
とは限りません。
たとえば、1リクエストを100msで処理できるサーバーがあるとします。
でも、同時に1リクエストしか処理できないなら、単純計算では1秒間に10件くらいしか処理できません。
Latency: 100ms
Concurrency: 1
Throughput: 約10 req/s
一方で、同じ100msの処理でも、100件を同時に処理できるなら話が変わります。
Latency: 100ms
Concurrency: 100
Throughput: 約1,000 req/s
ということもありえます。
つまり、Latencyが同じでもConcurrencyによってThroughputは変わります。
ざっくり言うと、
- Latency: 1件にどれくらい時間がかかるか
- Concurrency: 同時に何件処理できるか
- Throughput: 結果として一定時間に何件処理できるか
という感じです。
なので、Latencyだけを見て「このシステムは大量のリクエストにも強い」と判断することはできません。
Web APIではLatencyが気になりやすい
たとえば、ECサイトの商品ページを開くケースを考えてみます。
Browser -> GET /products/123 -> API -> Response
このAPIが100msで返るのと3秒かかるのでは、かなり体感が違います。
ユーザーが直接待つような処理では、Latencyが重要になりやすいです。
もちろん、大量アクセスがあるサービスならThroughputも必要です。
ただ、
Throughput: 10,000 req/s
p95 Latency: 5秒
だったら、かなり使いづらい可能性があります。
大量に処理できることと、1人ひとりのユーザーが快適に使えることは別の話です。
バッチ処理ではThroughputが重要になることもある
逆に、ユーザーがその場で結果を待っていない処理では、Throughputの方が重要になることがあります。
たとえば、
100万枚の画像を変換する
という処理を考えます。
1枚あたりの処理時間が、
100ms -> 90ms
になったとしても、全体として同時に少ししか処理できないなら、そこまで大きな改善にならないかもしれません。
それよりも、
100 images/sec -> 1,000 images/sec
のように、単位時間あたりに処理できる量を増やした方が効果が大きいことがあります。
たとえばWorkerを増やして、
Job Queue -> Worker A
Job Queue -> Worker B
Job Queue -> Worker C
Job Queue -> Worker D
のように並列処理するイメージです。
1件あたりのLatencyはほとんど変わっていなくても、全体のThroughputは上げられます。
IoTでも処理によって変わる
IoTでも同じです。
たとえば大量のデバイスからテレメトリを受け取る仕組みを考えます。
Device -> MQTT Broker -> Consumer -> Database
数万台のデバイスから定期的にデータが送られてくるなら、
1メッセージが20msで処理されるか30msで処理されるか
よりも、
1秒間に何万メッセージ処理できるか
の方が重要になることがあります。
この場合はThroughputです。
一方で、たとえばドローンやロボットに緊急停止コマンドを送る処理ならどうでしょう。
Server -> Command -> Device
この場合、
1秒間に何万件の緊急停止命令を処理できるか
より、
コマンドを送ってからどれくらいで届くか
の方が気になります。
こちらではLatencyが重要です。
つまり、同じシステムの中でも、
- テレメトリ受信はThroughput
- リアルタイム制御はLatency
のように、処理によって重要な指標が変わります。
「このシステムはLatency重視」「このシステムはThroughput重視」と大きく分けるより、処理ごとに考えた方が自然なこともあります。
Throughputの限界に近づくとLatencyが悪化する
LatencyとThroughputは別の指標ですが、完全に無関係ではありません。
たとえば、あるサーバーが最大で1,000 req/sくらい処理できるとします。
そこに500 req/sしか来ていないなら、かなり余裕があります。
Incoming: 500 req/s
Capacity: 1,000 req/s
この状態なら、リクエストが来てもすぐに処理できるので、Latencyも安定しやすいです。
でも負荷が増えて、
900 req/s
950 req/s
990 req/s
のように限界へ近づいてくると、処理待ちが発生するようになります。
Requests -> Queue -> Server
という状態です。
サーバーが実際に処理している時間は同じでも、Queueで待たされる時間が増えれば、ユーザーから見たLatencyは悪化します。
さらに、
Incoming: 1,200 req/s
Capacity: 1,000 req/s
になったとします。
毎秒1,200件来るのに、毎秒1,000件しか処理できません。
すると、毎秒200件ずつ処理待ちが増えていきます。
こうなると、
- Throughputは1,000 req/s付近で頭打ち
- Queueは伸び続ける
- Latencyだけどんどん悪化する
という状態になります。
なので負荷試験でも、
最大で何req/s出せるか
だけを見るのではなく、
負荷を増やしたときにLatencyがどう変化するか
も一緒に見た方がいいです。
平均Latencyだけを見るのも危ない
Latencyを見るときは、平均値だけを見るのも少し注意が必要です。
たとえば、
Average Latency: 100ms
だけを見ると、かなり速そうに見えます。
でも実際には、
p50: 50ms
p95: 300ms
p99: 2,000ms
かもしれません。
この場合、大半のリクエストは速いですが、一部のリクエストは2秒以上かかっています。
平均値だけだと、この遅いリクエストが見えづらくなります。
なのでAPIのLatencyを見るときは、
- p50
- p95
- p99
のようなPercentileを見ることがあります。
たとえば、
p95 = 300ms
なら、
リクエストの95%は300ms以内に終わった
という意味です。
単純に平均だけを見るより、遅いリクエストがどれくらい存在しているかもわかります。
結局どちらを最適化すればいいのか
これは結局、システムや処理によります。
傾向としては、
| 処理 | 重視されやすい指標 |
|---|---|
| Web API | Latency |
| バッチ処理 | Throughput |
| 大量のメッセージ処理 | Throughput |
| IoTテレメトリ | Throughput |
| リアルタイム制御 | Latency |
くらいには分けられます。
ただ、
WebだからLatency
バッチだからThroughput
と単純に決められるわけでもありません。
Web APIでも大量アクセスを受けるならThroughputが必要ですし、バッチ処理でも完了時間に厳しい要件があるかもしれません。
なので、最初から、
LatencyとThroughputのどちらを改善するべきか
と考えるより、
この処理では何が遅いと困るのか
どれくらいの量を処理できないと困るのか
から考えた方がいいと思います。
たとえば、
p95 Latency < 300ms
Throughput > 5,000 req/s
のように、両方に要件があることも普通です。
必要なLatencyを満たしながら、必要なThroughputも確保する。
実際にはそういう考え方になることが多いです。
「性能が良い」だけだと少し曖昧
「このシステムは速い」という表現は、よく考えるとかなり曖昧です。
Latencyが低いことを言っているのかもしれません。
Throughputが高いことを言っているのかもしれません。
たとえば、
1件の処理はかなり速いけど、大量アクセスには弱い
というシステムもあります。
逆に、
大量のデータは処理できるけど、1件あたりの処理には時間がかかる
というシステムもあります。
なので性能について話すときは、
何が速いのか
を分けて考える必要があります。
その基本になるのがLatencyとThroughputです。
ざっくり覚えるなら、
Latency = 1回の処理でどれくらい待つか
Throughput = 一定時間でどれくらい捌けるか
くらいで考えておけば、まずは十分だと思います。