/proc/diskstats
の出力を見ると、読み取りに費やされた合計時間、書き込みに費やされた合計時間、およびIOを実行する合計時間の間に不一致があることに気づきました。たとえば、/proc/diskstats
には次のようなエントリがあります。
$ cat /proc/diskstats
...
8 0 sda 944150584 590524 235547588959 780672196 833280352 534699043 322507689696 3472000824 1 812190100 4246357772
...
https://www.kernel.org/doc/Documentation/iostats.txt にあるドキュメントによると、
フィールド4-読み取りに費やされたミリ秒数これは、すべての読み取りに費やされた合計ミリ秒数です(__make_request()からend_that_request_last()まで測定)。
フィールド8-書き込みに費やされたミリ秒数これは、すべての書き込みに費やされた合計ミリ秒数です(__make_request()からend_that_request_last()まで測定)。
フィールド10-I/Oの実行に費やされたミリ秒数このフィールドは、フィールド9がゼロ以外である限り増加します。
したがって、合計IO時間は読み取りに費やされた時間と書き込みに費やされた時間の合計であると期待するので、10番目のフィールドは4番目と8番目のフィールドの合計になると期待します。ただし、これが事実であることに気づいたことはありません。さらに、4番目と8番目のフィールドの合計が10番目より大きいことを常に観察しました(たとえば、上の行では(780672196 + 3472000824-812190100)。 = 3440482920)これらの数値が異なる理由を誰かが説明できるかどうか疑問に思っていましたが、10番目のフィールドは4番目と8番目のフィールドの合計とは異なる何かをキャプチャしようとしているようです。
私はソースコードを見ていませんが、違いは2つの異なる会計モードに由来するようです。
#4と#8のフィールドは、eachリクエストが完了するまでの時間の合計です。これは、並行して発行されたリクエストがそれぞれカウントの増加に貢献していることを意味します。
#10フィールドは、キューとディスクがビジーだった実際の時間のみをカウントするため、並列に発行されたリクエストを1つのリクエストとしてカウントします。
実際の例を見てみましょう。オン/boot
パーティション、私はdd
〜4 MBファイル。統計を見てください:
[root@localhost boot]# cat /proc/diskstats | grep sda1
8 1 sda1 46256 0 255703 19332 2063 0 4162 538 0 11207 19862
[root@localhost boot]# dd if=initramfs-0-rescue-7dc32e3935ba4ce1ae50a0a8170e4480.img of=/dev/null
84099+1 records in
84099+1 records out
43058701 bytes (43 MB) copied, 0.347783 s, 124 MB/s
[root@localhost boot]# cat /proc/diskstats | grep sda1
8 1 sda1 46342 0 339807 23011 2063 0 4162 538 0 11551 23540
[root@localhost boot]#
ファイルを読み取るには、約0.35秒、つまり約350ミリ秒かかりました。ただし、カウンター#4と#10は非常に異なる方法で反応します。最初の増加は約4000、後者は約350だけです。「正しい」値を持つものは簡単にわかります。これは、フィールド#10です。 dd
操作全体に約350ミリ秒かかり、フィールド#10はこれと同じ量だけ増加しました。
それでは、なぜフィールド#4がそれほど大きく増加したのか、そしてそれが実際に何を測定しているのか?
まず、要求レベルで何が起こっているのかを理解しましょう。 dd
はデフォルトで512Bリクエストを使用しますが、Linuxページキャッシュは4KBの粒度で動作するため、約1000 x 4KBのリクエストを想定しています。これらの1000の要求はキューに入れられ、1つずつ発行されます(簡単にするために、NCQが存在しないとしましょう)。メカニカルディスクはシーケンシャルリードに優れているため、通常、先読みポリシーを使用します。つまり、必要以上のデータを読み取ります。つまり、最初の4Kリクエストが完了した後、他のすべてのリクエストは非常に短時間で処理されます。
野生の簡略化を使って、いくつかの数学をやってみましょう:
フィールド#4で測定した合計リクエスト時間:1000キュー内リクエスト* 4ms each == 4000ms。そして、これはおおよそフィールド#4が増加した値です...
最終行:
近似的な並列処理を描画するには:マルチコアCPUを考えてください。 2つのプロセスが同時にCPUを叩き、それぞれ60秒間実行できます。使用される合計CPU時間は120秒(60秒* 2)ですが、2つのプロセスが同時に実行されるため、実際の経過クロック時間は合計60秒のままです。