🔩 ねじき教室 Go と Web の教室

1 リクエストがリソースをどれだけ使うか

読了目安 約4分

サービス需要という 1 つの数字でボトルネックと容量を表し、あらゆる改善策を同じ物差しに載せます。

この章の目次

「MySQL が重い」は、まだ数字になっていません。 どれくらい重いのか、いま何件まで捌けるのか、直すと何件になるのか。 ここが数字になると、直す場所を選べます。

リソースは時間で数える

CPU の 1 秒は 30 億回の刻み のとおり、CPU を使った量は時間で数えられます。 1 つのコアは同時に 1 つの処理しか進められないので、1 コアの能力は「1 秒のあいだに 1 秒ぶん働ける」です。 4 コアなら、1 秒のあいだに 4 秒ぶんです。

1 秒しか経っていないのに 4 秒ぶん、というのは奇妙に見えるかもしれません。 4 人が 1 秒ずつ働けば、こなせる仕事の量は 4 秒ぶんです。

使った側も同じ物差しで数えます。 ある処理がコアを 8 ミリ秒占有したなら、使った量は 8 ミリ秒です。 能力と消費が同じ単位になるので、割り算ができます。

サービス需要

サービス需要は、1 リクエストを処理するために、あるリソースを占有する時間です。 記号は DD を使います。

D=そのリソースが忙しかった時間処理できた件数 D = \frac{\text{そのリソースが忙しかった時間}}{\text{処理できた件数}}

材料は、CPU の使用率とベンチマーカーの結果です。 どちらも Part 6 の計測ですでに手元にあり、新しく測るものはありません。

4 コアのデータベースで、1 秒のあいだに 4 つのコアが合計 3.2 秒ぶん働き、400 件を処理したとします。

D=3.2 秒400 件=0.008 秒=8 ミリ秒 D = \frac{3.2\ \text{秒}}{400\ \text{件}} = 0.008\ \text{秒} = 8\ \text{ミリ秒}

1 件を処理するのに、CPU を 8 ミリ秒ぶん使うということです。

容量が計算できる

使えるのは 1 秒あたり 4 秒ぶん、1 件につき 0.008 秒使う。 この 2 つを割ると、毎秒何件まで捌けるかの上限 XmaxX_{\max} が出ます。

Xmax4 秒0.008 秒=500 件/秒 X_{\max} \le \frac{4\ \text{秒}}{0.008\ \text{秒}} = 500\ \text{件/秒}

いま 400 件なら、飽和まで 2 割しか余裕がありません。 飽和の手前では待ち時間が跳ね上がるので、実際にはこれより手前で応答時間が悪化します。

全リソースで計算すると、いちばん D の大きいリソースが全体の上限を決めています。 それがボトルネックです。

需要は「何回使うか」と「1 回いくらか」に分かれる

サービス需要は、さらに 2 つに分解できます。

D=V×S D = V \times S
  • VV :1 リクエストがそのリソースを使う回数。データベースならクエリの本数
  • SS :1 回あたりにかかる平均時間。データベースならクエリ 1 本の実行時間

この分解が効くのは、改善策がどちらを下げるものなのかがはっきりするからです。

改善策下がるもの
N+1 の解消V(クエリ本数)
キャッシュV(そもそも使わない)
インデックスS(1 本が速くなる)
一括 INSERTV(往復をまとめる)
不要なカラムを取らないS(転送量が減る)

100 本のクエリが 1 本 1 ミリ秒なら D は 100 ミリ秒です。 1 本を 0.5 ミリ秒に半減させても 50 ミリ秒ですが、本数を 3 本に減らせば 3 ミリ秒です。 V が大きいときは、S をいくら削っても勝てません。

しかも S には、往復の時間が下限として残ります。 別のマシンにあるデータベースなら、どれだけクエリを速くしても 1 本あたり 200 マイクロ秒は消えません。 V を減らす手が強いのは、この下限ごとまとめて消せるからです。

使用率が同じでも改善している

使用率だけを見ていると、次のような改善を見落とします。

変更前変更後
CPU 使用率90%90%
処理できた件数300/秒600/秒

使用率は動いていませんが、D は半分になっています。 同じリソースで倍の仕事をしているので、これは明確な改善です。

だから記録すべきなのは使用率ではなく、1 件あたりの数字です。

  • 1 件あたりのアプリ CPU 時間、データベース CPU 時間
  • 1 件あたりのクエリ本数、走査行数、ロック待ち時間
  • 1 件あたりの転送バイト数

試してみよう

ある計測で、次の数字が取れたとします。 ベンチマーカーは 60 秒走り、成功した件数は 12,000 件でした。

コア数60 秒間の CPU 使用時間の合計
アプリ496 秒
データベース2108 秒
  1. それぞれの DD を求めてください
  2. それぞれの上限件数を求めてください(コア数 ÷D\div D です)
  3. 先に飽和するのはどちらですか
  4. いま毎秒何件で、上限に対してどこまで来ていますか
答えを見る

DD はアプリ 8 ミリ秒、データベース 9 ミリ秒。上限はアプリ 500 件/秒、データベース 222 件/秒。先に飽和するのはデータベースです。いまは毎秒 200 件なので、上限の 9 割に達しています。前章の表でいえば ρ=0.9\rho = 0.9 、待ち時間が 9 倍になっている状態です。

アプリのコアはまだ 4 割しか使われていません。 ここでアプリの台数を増やしても、データベースは 1 ミリも楽になりません。