今日は研究室の某ストレージの再設定をしてました。 年末に諸々の事情により業者がやってきて、OSもストレージの設定も全部消去していったまま放置していたので、 いい加減キレイサッパリ心も新たな気持ちで使い始めるべく設定設定。
それで、昨年末にストレージの性能を色々と調べてみてどうも性能が変なポイントがあったので、 改めて調べてみたらGNU partedの使い方を自分がよくわかっていなかった、ということがわかったのでメモしておきます。
変なポイントというのが、
/dev/sdb
を3つのパーティションに切って /dev/sdb1
、/dev/sdb2
、/dev/sdb3
の3つで使っていたのですが、
/dev/sdb
に対して直接IOを発行したり、/dev/sdb3
に対して直接IOを発行するときにはカタログ通りのIO性能が出るのに、
/dev/sdb1
、/dev/sdb2
に対してIOを発行するとカタログの1/5くらいのIO性能しか出ない、というもの。
結論から言うと、パーティションの境界がうまくアラインメントされておらず、
OSのレベルでIOリクエストのremapが発生していたことが性能低下の原因でした。
パーティションを切るときには、最近はGNU partedを使っているのですが、partedのmkpartはMB(メガバイト)とかGB(ギガバイト)を単位で指定できます。たとえば、 parted /dev/sdb mkpart primary 8602M 17204M
みたいな感じ。
このMBが曲者で、ディスクの容量を語るときの10進接頭辞のメガバイト=10の6乗になっていました。
こちらとしては2進接頭辞のメガバイト=2の20乗だと思っていたので、
まあ普通にアラインメントされているだろうと思っていたら、全くそんなことはなかった、ということです。
実はちゃんとGNU partedのヘルプを読むと、 2進接頭辞のメガバイトを明示するためのメビバイト(MiB)も単位として使えるようになっていることがわかります。
# parted /dev/sdb
GNU Parted 1.8.1
/dev/sdb を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) help unit
unit UNIT デフォルトの単位を UNIT にする
UNIT は次のうちから選びます: s, B, kB, MB, GB, TB, compact, cyl, chs, %, kiB, MiB, GiB, TiB
思い込みって怖いですね、ほんと。。。
IOリクエストがremapされているかどうか調べる
blktrace
を使うと、OSのレベルでIOリクエストの1個1個がどう処理されているかを調べることができます。
アラインメントされているデバイスにIOを発行している最中のblktrace
の出力は次のようになります:
8,16 20 15 0.001015709 2269 D R 18500512 + 16 [(null)]
8,16 20 16 0.001028970 2269 Q R 31519040 + 16 [(null)]
8,16 20 17 0.001031031 2269 G R 31519040 + 16 [(null)]
8,16 20 18 0.001032779 2269 I R 31519040 + 16 [(null)]
8,16 20 19 0.001036923 2269 U N [(null)] 63
(snipped)
D,Q,G,I とかいうのがそれぞれ処理内容を表していて、IO完了、IOディスパッチなどなどに対応します。
これが、アラインメントされていないデバイスの場合には次のようになります。
8,16 31 20 0.000073403 2336 D R 14528658 + 16 [(null)]
8,16 31 21 0.000087055 2336 A R 11186162 + 16 <- (8,17) 11186128
8,16 31 22 0.000087458 2336 Q R 11186162 + 16 [(null)]
8,16 31 23 0.000088360 2336 G R 11186162 + 16 [(null)]
8,16 31 24 0.000089168 2336 I R 11186162 + 16 [(null)]
8,16 31 25 0.000089977 2336 D R 11186162 + 16 [(null)]
8,16 31 26 0.000105543 2336 A R 12207330 + 16 <- (8,17) 12207296
(snipped)
新たにAという処理が行われていることがわかります。これがIOのremap処理です。 remap処理が入ると、なんかIO性能がガタっと落ちてしまうようです。 暇な人はカーネルのソースを読んでなんで性能が落ちるのか教えてください。
(追記) アラインメントされたパーティションでもremapは発生してた
アラインメントされていようがいまいが、デバイスを複数のパーティションに切って、 各パーティションに対してIOリクエストを出すとremapは発生していました。blktrace確認。 アラインメントが揃っていないと、remapのときの処理内容が重くなってIO性能が出ないようになってしまうのかな?
ツイート