Everyday Deadlock

by hayamiz.com

GNU partedの罠

2013/01/30

今日は研究室の某ストレージの再設定をしてました。 年末に諸々の事情により業者がやってきて、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性能が出ないようになってしまうのかな?

category: technology
tags: storage, linux, and tips
このエントリーをはてなブックマークに追加

この記事にコメントする

comments powered by Disqus


このエントリーをはてなブックマークに追加