web-dev-qa-db-ja.com

`dd`はフルスピードで実行していますが、ディスク使用率は20%しかありません。どうして?

  1. Sudo dd if=/dev/sda of=/dev/null bs=1M iflag=direct
  2. atopsar -d 5 # in a second terminal
  3. top # in a third terminal

atopsarの結果:

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:16:50  sda             18%  156.5  1024.0     0.0     0.0   5.0   1.15 ms
19:16:55  sda             18%  156.3  1024.0     0.0     0.0   4.9   1.15 ms
...

ディスク使用率(「ビジー」)が100%未満と報告されるのはなぜですか?

topによると、ddプロセスはCPUの3%以下しか使用しません。 topは、システムのCPUのハードウェアおよびソフトウェア割り込み(hiおよびsi)の使用状況の全体的なレポートも提供します。これは1%未満と表示されます。私は4つのCPU(それぞれ2つのスレッドを持つ2つのコア)を持っています。

/dev/sdaはSATA HDDです。 SSDではなく、ハイブリッドSSHDドライブでもありません。 1秒あたり約150メガバイトより速く読み取ることはできません:-)。結果のその部分は理にかなっています:156読み取り/秒* 1024 KB /読み取り= 156 MB /秒

カーネルのバージョンは5.0.9-200.fc29.x86_64です。 Fedora Workstation 29のかなりデフォルトの簡単なインストールがあります。これはVMではありません。 IOスケジューラはmq-deadlineです。

カーネルバージョン5.0以降、Fedoraはマルチキューブロックレイヤーを使用します。単一のキューブロックレイヤーが削除されたためです:-)。

atopsar -dおよびatopのディスク使用率の数値は、 kernel iostat fields の1つから計算されていると思います。リンクされたドキュメントには、「フィールド10-I/Oの実行に費やされたミリ秒数」が記載されています。さらに詳細な定義もありますが、言及されている関数がマルチキューブロックレイヤーにまだ存在するかどうかはわかりません。私が知る限り、atopsar -datopはどちらも 共通コード を使用してこのフィールドを読み取ります(このフィールドはsar -dでも使用されていると思います)/iostat -x/mxiostat.py

追加のテスト

バリエーション2:bs=512kに変更しますが、iflag=directを維持します。

dd if=/dev/sda of=/dev/null bs=512k iflag=direct

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:18:00  sda             35%  314.0   512.0     0.0     0.0   2.1   1.12 ms
19:18:05  sda             35%  313.6   512.0     0.2     4.0   2.1   1.11 ms

バリエーション3:bs=1Mを使用しますが、iflag=directを削除します。 ddは約10%のCPUと35%のディスクを使用します。

dd if=/dev/sda of=/dev/null bs=1M

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:21:47  sda             35%  242.3   660.2     0.0     0.0   5.4   1.44 ms
19:21:52  sda             31%  232.3   667.8     0.0     0.0   9.5   1.33 ms

これらの結果を再現する方法-重要な詳細

最後のテストに注意してください。つまり、ddwithoutiflag=directを実行します

それはちょっと豚のようなものです。システム(マウスカーソル)が10秒以上フリーズするのを見ました。スワップを無効にしたときでも。 (テストはRAMを buff/cache で埋めます。これは非アクティブなLRUリストを埋めています。回転率が非アクティブなキャッシュページを比較的迅速に排除すると思います。同時に、ディスク順次読み取りでビジー状態であるため、ページインが必要になると時間がかかります。これがどの程度悪化するかは、カーネルが最終的にアクティブLRUリストをめくってしまうか、それとも縮小しすぎるかによって異なります。つまり、現在の状態- "コーナーケースとさまざまな最適化をキャッチするためにいくつかの変更を加えたいくつかの異なるアルゴリズムのマッシュ" があなたのケースで機能しています)。

の 正確 元のテストの結果は再現が困難です。

KB/read512ではなく1024と表示されることがあります。この場合、他の結果はbs=512kの結果に似ています。これを含めると、約20%ではなく、約35%のディスク使用率が示されます。だから私の質問はどちらの場合にも成り立ち、違いはちょっと混乱します。

違いは他のプロセスからのIOが原因である可能性があると思いました...例Firefoxを開いて結果をこの質問に書き始めたとき...しかし、Firefoxを実行せずにそれを確認したこともあります。

最初に再起動してログインし、システムIOがゼロに落ち着くのを待って(たとえば、Pac​​kageKitチェックを終了する)後に実行すると、テストはKB/read = 1024を示す傾向があると思います。


いくつかの追加情報が要求されました。 ここに追加情報があります ですが、私の意見では、これ以上質問に光を当てるものではありません。

8
sourcejedi

これは、カーネルバージョン5.0での変更の結果です。

ブロック:part_round_statsを削除し、 精度の低いカウントに切り替える

CPUごとのin_flightカウンターに変換します。

関数part_round_statsはJiffyごとにin_flightカウンターを必要とします。Jiffyごとにすべてのpercpu変数を合計するにはコストがかかりすぎるため、削除する必要があります。 part_round_statsは、time_in_queueとio_ticksの2つのカウンターを計算するために使用されます。

time_in_queueは、part_round_statsなしで、I/Oの終了時にI/Oの期間を追加することで計算できます(値は、進行中のI/Oの時間はカウントされないことを除いて、以前に計算された値とほぼ同じです)。

io_ticksは、I/Oが開始または終了し、jiffies値が変更されたときに値を増やすことによって概算できます。 I/OがJi​​ffyより少ない場合、値は以前に計算された値と同じです。 I/OがJi​​ffyを超える場合、io_ticksは以前に計算された値よりも遅れることがあります。

io_tickspart_stat_show() で使用され、 kernel IO stat を「フィールド10-実行に費やされたミリ秒数」に提供します/ Os」)。

これは私の結果を非常にうまく説明します。 Fedoraカーネル構成では、 " Jiffy "は1ミリ秒です。大規模な読み取りが期待されますIO ddによって送信されたものは、1つまたは2つ以上の保留中になる可能性があります。特に、旧式の機械式HDDを使用する私のシステムでは。

以前のカーネルシリーズ4.20.xに戻ると、正しいディスク使用率が表示されます。

$ uname -r
4.20.15-200.fc29.x86_64
$ atopsar -d 5
...
13:27:19  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
13:28:49  sda             98%  149.4  1024.0    13.0     5.3   2.2   6.04 ms
13:28:54  sda             98%  146.0  1024.0     7.2     5.7   1.5   6.38 ms

この古いカーネルは、従来のシングルキューブロックレイヤーと、デフォルトでcfq IOスケジューラーを使用しました。deadline IOスケジューラーを使用した場合も、結果は同じです。 。


誰かが近似を調整するパッチを提案していることにも気づきました。コンスタンティン・フレブニコフから:

[PATCH 3/3] block/diskstats:遅いディスクのio_ticksのより正確な近似

現在io_ticksは、jiffiesが変更された場合、リクエストの最初と最後に1つずつ追加することで概算されています。これは、Jiffyより短いリクエストに対しては完全に機能します。

遅いリクエストの修正は簡単です。リクエストの最後に、最後の更新以降に渡されたjiffieの数を追加します。


しかし、コードを見ると、2つ目の懸念がありました。 io_ticksはCPUごとのディスク統計です。個々のCPUごとに増加しているように見えます(ディスクの統計を読み取ると合計されます)。したがって、少なくとも場合によっては、CPUの数を掛けた過大評価になることもあると思います。

技術的には、リンクされたコードは "bio layer" に属します。 CPUごとの統計情報への切り替えは非常に高速なストレージデバイスをサポートすることを目的としていましたが、実際には新しいマルチキューの内部 リクエストレイヤー には依存していません。

7
sourcejedi