← システム性能分析のしくみ コース
8. iostatの読み方 — %utilが100%でも飽和とは限らない
iostat のデバイス列がそれぞれ「何を数えているのか」を、1件のI/Oがたどる経路に沿って図で追っていきましょう。
① 1件のI/Oがたどる経路
アプリ / ファイルシステムread() や write() がブロック層に届く
隣接I/Oはここでマージされる
キューで待つ先行I/Oが処理中なら順番待ち
デバイスが処理する実際にディスク / SSD が読み書きする
処理が終わる
完了(completed)この瞬間に r/s・w/s へ1件カウントされる
- ・man の定義どおり r/s・w/s は「完了した(completed)」リクエスト数を毎秒で数えたものです
- ・r/s・w/s はマージ後(after merges)の件数です。rrqm/s の定義が「デバイスへキューされた際にマージされた数」であるとおり、マージはデバイスに届く前に起きます
iostat の列は、この経路のどこを測っているかで役割が分かれます。まずこの流れを頭に置いてください。
② awaitは「キュー待ち+デバイス処理」の合計
デバイスに発行された時刻ここから計測が始まる
計測区間の始まり
キューで待った時間time spent by the requests in queue
処理にかかった時間time spent servicing them
2つを足して平均をとる
r_await(読み)読みリクエスト1件あたりの平均ミリ秒
w_await(書き)書きリクエスト1件あたりの平均ミリ秒
- ・man は「issued to the device to be served」までの平均時間と定義し、待ち時間と処理時間の両方を含むと明記しています
- ・読みと書きは特性が違うため r_await と w_await に分かれています。片方だけ悪化することがよくあります
- ・await は平均値なので、少数の極端に遅いI/Oは平均に埋もれます
await が伸びたとき、それが「待たされたせい」なのか「処理自体が遅いせい」なのかは、この列だけでは切り分けられません。
③ なぜawaitは待ち時間で伸びるのか
キューにほぼ0件発行したらすぐ処理される
到着ペースが処理ペースを上回りはじめる
キューに数件たまる自分の前の数件が終わるまで待つ
さらに到着が増える
待ちが処理より支配的になるawait の大半がキュー待ち時間になる
結果として
await が跳ね上がる処理時間は変わっていないのに遅く見える
- ・待ち行列では、到着ペースが処理能力に近づくほど待ち時間の伸び方が急になります
- ・1件あたりの処理時間が変わらなくても、await は待ち時間だけで何倍にもなり得ます
「デバイスは同じ速さなのにレイテンシが悪化した」の正体は、多くの場合この待ち時間の増加です。
④ aqu-szは「処理中を含む」平均の実行中件数
aqu-szaverage queue length of the requests issued to the device
カーネル側の実体を見ると
diskstats の field 9I/Os currently in progress(処理中を含む在庫数)
それを時間で重み付けした平均待機中だけでなく処理中の件数も入る
したがって await とは独立でない
aqu-sz ≒ スループット × awaitLittle の法則どおり両者は連動する
- ・aqu-sz は「順番待ちの行列の長さ」ではなく、処理中のものも含めた平均の実行中(in-flight)件数です
- ・そのため aqu-sz と await は独立した2つの手がかりではありません。おおむね aqu-sz =(r/s × r_await)+(w/s × w_await)という関係で結ばれています
- ・「aqu-sz が小さいのに await が長い」は、単にIOPSが低いことを意味します。デバイスが遅いことの証拠にはなりません
- ・妥当な値はデバイスの並列度で変わります。逐次デバイスでは 1 前後で既に飽和、NVMe では数十でも余裕がある場合があります
aqu-sz は待ち行列の長さではなく、処理中を含む平均の実行中件数です。await とは数式で連動するため、別々の証拠としては使えません。
⑤ %utilが数えているのは「時間の割合」だけ
観測した経過時間iostat の集計間隔
そのうち
I/Oが1件以上発行されていた時間percentage of elapsed time during which I/O requests were issued
1件も発行されていなかった時間完全な待機
前者の割合が
%util忙しかった「時間の割合」であって、処理量の割合ではない
- ・カーネル側の元データ(diskstats field 10)は「実行中件数が1以上である限り増える」時間であり、同時に何件処理していたかで重み付けされません
- ・そのため %util は1件でも100件でも等しく「忙しい」と数えます。ここが aqu-sz との決定的な違いです
- ・man の表現も bandwidth utilization であり、デバイスの性能上限に対する使用率ではありません
ここが最大の誤解ポイントです。%util は「暇でなかった時間の比率」を示すだけの指標です。
⑥ 並列に処理できるデバイスでは100%でも余力が残る
逐次に処理するデバイス一度に1件しか処理できない
並列に処理するデバイスRAIDアレイや現代のSSD / NVMe
%util が100%のとき、それぞれ何が起きているか
常に1件を処理し続けているこれ以上詰めても待ちが増えるだけ
常に1件以上が発行されている同時に何件処理中かは不明
したがって
飽和の目安として使える100%に近ければ限界に近い
飽和の目安にならない性能上限を反映しない
- ・man ページ自身が、100%に近い値は逐次にリクエストを処理するデバイス(devices serving requests serially)では飽和を意味するが、RAIDアレイや現代のSSDのように並列に処理するデバイスではこの数値は性能上限を反映しない、と明記しています
- ・NVMe SSD は複数のキューと多数の同時要求を扱えるため、%util が100%でも実際にはまだスループットを伸ばせることがあります
%util が100%という事実だけでは、そのデバイスが限界かどうかを判断できません。デバイスの種類を先に確認してください。
⑦ 判断の手順:%utilだけで結論を出さない
%util を見る忙しい時間の割合。ここは入口にすぎない
まずデバイスの並列度を確認する
逐次デバイスなら100%付近は飽和とみてよい
NVMe / RAID なら100%でも余力の判断はできない
次に実際のレイテンシを見る
await が業務要件を満たすか1件あたり何ミリ秒かかっているか
aqu-sz でどれだけ詰まっているか実行中件数が並列度に見合うか
await が長いときの切り分け
aqu-sz も大きい同時要求が多い。負荷側を絞ると改善しうる
aqu-sz が小さいIOPSが低いだけ。1件の遅さを別途調べる
- ・最終的な判断基準は %util ではなく、await が業務要件のレイテンシに収まっているかどうかです
- ・r/s・w/s と rareq-sz・wareq-sz(平均リクエストサイズ)も併せて見ると、件数が多いのかサイズが大きいのかを区別できます
- ・rrqm/s・wrqm/s と %rrqm・%wrqm はマージされた量を示し、デバイスに届く前に何件がまとめられたかを表します
%util は「見に行くきっかけ」であって結論ではありません。デバイス種別を確かめ、await が要件を満たすかで判断してください。