xfsファイルシステムのデフラグ方法とパフォーマンスについて

Hard Disk Head

4/1のエントリで、頑張ってブログを書く頻度を上げます、と言ったまま4日が経過し、このままだとただのエイプリルフールの戯言になりかねないと思ったので、ちょっと調べてみたログを残します。

XFSの設計はエクステントベースで、ファイルの内容は1つ以上のエクステントと呼ばれる連続的な領域内に保存されている。XFSファイルシステム内のファイルは、ユーザーの使い方によってはフラグメント化することがあるが、xfs_fsrユーティリティを使ってそのようなファイルをデフラグすることでファイルアクセスについてのシステムの性能を向上させることができる。

xfs_fsrを使ってXFSファイルシステムをベストの状態で使用する (1/2) - ITmedia エンタープライズ

ココの部分の使い方を実際に試してみることにしました。

まず、用意したのは、xfsファイルシステムで2年くらい運用して役目を終えた、とあるサーバ(ハードディスク搭載、ディスクI/O多数)です。

デフラグのやり方

さて、まずフラグメンテーション度合い(断片化量)を測定してみます。コマンドは↓のような感じでパーティションを指定します。

# xfs_db -c frag -r /dev/sdb1
actual 343, ideal 259, fragmentation factor 24.49%

正直、数字はピンとこないのですが、理想長に対して実長が長いので、幾分か断片化しているということなのでしょう。

実際にいくつかのファイルを確認してみたところ、エクステントが分割されたような形になっていました。
たとえば、

# xfs_bmap -v /data/foo/hoge.1
/data/foo/hoge.1:
 EXT: FILE-OFFSET         BLOCK-RANGE           AG AG-OFFSET            TOTAL
   0: [0..108255]:        626753792..626862047  82 (4831024..4939279)  108256
   1: [108256..3195615]:  629540024..632627383  83 (32832..3120191)   3087360
   2: [3195616..4192255]: 643381216..644377855  84 (6289600..7286239)  996640

こんな感じです。
こいつを最適化するには、"xfs_fsr"コマンドを使います。このコマンドはCentOSだとxfsdumpパッケージに含まれるので、

# yum install xfsdump

こんな感じでインストールしましょう。

# xfs_fsr /data/foo/hoge.1

その後、↑のような感じでコマンドを実行すると、今回の例だと"hoge.1"ファイルの最適化が実施されます。

# xfs_bmap -v /data/foo/hoge.1
/data/foo/hoge.1:
 EXT: FILE-OFFSET      BLOCK-RANGE           AG AG-OFFSET          TOTAL
   0: [0..4192255]:    712935920..717128175  94 (64..4192319)    4192256

おお。結果、フラグメントの状態はこんな感じに最適化されました。

で、このコマンドは↑のように1ファイルに対するだけじゃなくて、パーティションを指定して、ファイルシステム全体を最適化したり、制限時間を設けること(利用が少ない深夜帯だけ実行するとか。)もできます。

# xfs_fsr /dev/sdb1
/data start inode=0

こんな感じでパーティションを指定して最適化。しばらく待つと処理は完了し、断片化量を調べてみると、、、

# xfs_db -c frag -r /dev/sdb1
actual 259, ideal 259, fragmentation factor 0.00%

こんな感じで最適化されました。

# xfs_bmap -v /data/foo/hoge.2
/data/foo/hoge.2:
 EXT: FILE-OFFSET         BLOCK-RANGE           AG AG-OFFSET            TOTAL
   0: [0..357295]:        626862048..627219343  82 (4939280..5296575)  357296
   1: [357296..3618527]:  637091680..640352911  84 (64..3261295)      3261232
   2: [3618528..4192255]: 650473952..651047679  85 (5797912..6371639)  573728

元々、↑な状態だったファイルも、、、

# xfs_bmap -v /data/foo/hoge.2
/data/foo/hoge.2:
 EXT: FILE-OFFSET      BLOCK-RANGE           AG AG-OFFSET          TOTAL
   0: [0..4192255]:    318546064..322738319  42 (256..4192511)   4192256

最適化後は、こんな感じで全ファイル綺麗に並んでおります。
めでたしめでたし。

パフォーマンスに関して

とはいえ、これって性能にどのくらい影響出ているのだろう?と思って、超超簡単に比較してみました。
適当に、断片化させまくった1GBのファイルを何パターンか作って、単純なシーケンシャルアクセスで読み出しにかかった時間を測ってみました。ちなみに都度OSキャッシュはdropさせています。


参考: Linuxのメモリ上のキャッシュを解放する - 元RX-7乗りの適当な日々

パターンA

# xfs_bmap -v /data/test1g_A
/data/test1g_A:
 EXT: FILE-OFFSET      BLOCK-RANGE       AG AG-OFFSET           TOTAL
   0: [0..2097151]:    230664..2327815    0 (230664..2327815) 2097152

まずは、こんな断片化していないファイルは、、、

# time cat /data/test1g_A > /dev/null

real    0m2.686s
user    0m0.012s
sys     0m0.339s

2.686秒でした。
以降、この環境が前提となります。

パターンB

# xfs_bmap -v /data/test1g_B
/data/test1g_B:
 EXT: FILE-OFFSET         BLOCK-RANGE         AG AG-OFFSET            TOTAL
   0: [0..131071]:        8446800..8577871     1 (862376..993447)    131072
   1: [131072..262143]:   8315728..8446799     1 (731304..862375)    131072
   2: [262144..1703935]:  8577872..10019663    1 (993448..2435239)  1441792
   3: [1703936..1835007]: 10257352..10388423   1 (2672928..2803999)  131072
   4: [1835008..1966079]: 10126264..10257335   1 (2541840..2672911)  131072
   5: [1966080..2097151]: 10388424..10519495   1 (2804000..2935071)  131072

この程度の断片化だと、

# time cat /data/test1g_B > /dev/null

real    0m2.798s
user    0m0.008s
sys     0m0.273s

2.798秒と、さほど差は出ません。
ケースバイケースだとは思いますが、シーケンシャルアクセスでは、フラグメンテーションはさほど気にしなくてもいいのかもしれません。


これ以上の断片化は、あまり遭遇しないかもしれませんが、せっかくなので作り出して測ってみましょうw

パターンC

# xfs_bmap -v /data/test1g_C
/data/test1g_C:
 EXT: FILE-OFFSET         BLOCK-RANGE       AG AG-OFFSET          TOTAL
   0: [0..32767]:         7806496..7839263   1 (222072..254839)   32768
   1: [32768..65535]:     8282960..8315727   1 (698536..731303)   32768
   2: [65536..98303]:     7524720..7557487   0 (7524720..7557487) 32768
   3: [98304..131071]:    6167744..6200511   0 (6167744..6200511) 32768
   4: [131072..163839]:   8053584..8086351   1 (469160..501927)   32768
   5: [163840..196607]:   6233280..6266047   0 (6233280..6266047) 32768
   6: [196608..229375]:   6279528..6312295   0 (6279528..6312295) 32768
   7: [229376..262143]:   7889744..7922511   1 (305320..338087)   32768
   8: [262144..294911]:   8184656..8217423   1 (600232..632999)   32768
   9: [294912..327679]:   8086352..8119119   1 (501928..534695)   32768
  10: [327680..360447]:   6377832..6410599   0 (6377832..6410599) 32768

・・・・・省略・・・・・

  50: [1736704..1769471]: 7098736..7131503   0 (7098736..7131503) 32768
  51: [1769472..1802239]: 6705512..6738279   0 (6705512..6738279) 32768
  52: [1802240..1835007]: 6902120..6934887   0 (6902120..6934887) 32768
  53: [1835008..1867775]: 7262576..7295343   0 (7262576..7295343) 32768
  54: [1867776..1900543]: 6803816..6836583   0 (6803816..6836583) 32768
  55: [1900544..1933311]: 7491952..7524719   0 (7491952..7524719) 32768
  56: [1933312..1966079]: 8250192..8282959   1 (665768..698535)   32768
  57: [1966080..1998847]: 7229808..7262575   0 (7229808..7262575) 32768
  58: [1998848..2031615]: 7773728..7806495   1 (189304..222071)   32768
  59: [2031616..2064383]: 7740960..7773727   1 (156536..189303)   32768

かなりフラグメンテーションさせまくりましたが、、、

# time cat /data/test1g_C > /dev/null

real    0m3.242s
user    0m0.009s
sys     0m0.355s

3.242秒です。遅くなってきましたが、大きくは劣化していませんね。

パターンD

# xfs_bmap -v /data/test1g_D
/data/test1g_D:
 EXT: FILE-OFFSET         BLOCK-RANGE       AG AG-OFFSET          TOTAL
   0: [0..2047]:          4891848..4893895   0 (4891848..4893895)  2048
   1: [2048..4095]:       4105408..4107455   0 (4105408..4107455)  2048
   2: [4096..6143]:       5096648..5098695   0 (5096648..5098695)  2048
   3: [6144..8191]:       4123840..4125887   0 (4123840..4125887)  2048
   4: [8192..10239]:      4187328..4189375   0 (4187328..4189375)  2048
   5: [10240..12287]:     4750528..4752575   0 (4750528..4752575)  2048
   6: [12288..14335]:     4877512..4879559   0 (4877512..4879559)  2048
   7: [14336..16383]:     4191424..4193471   0 (4191424..4193471)  2048
   8: [16384..18431]:     4093120..4095167   0 (4093120..4095167)  2048
   9: [18432..20479]:     4170944..4172991   0 (4170944..4172991)  2048
  10: [20480..22527]:     4207808..4209855   0 (4207808..4209855)  2048

・・・・・省略・・・・・

 992: [2066432..2068479]: 6005952..6007999   0 (6005952..6007999)  2048
 993: [2068480..2070527]: 6010048..6012095   0 (6010048..6012095)  2048
 994: [2070528..2074623]: 6001856..6005951   0 (6001856..6005951)  4096
 995: [2074624..2076671]: 6018240..6020287   0 (6018240..6020287)  2048
 996: [2076672..2078719]: 6042816..6044863   0 (6042816..6044863)  2048
 997: [2078720..2080767]: 6057152..6059199   0 (6057152..6059199)  2048
 998: [2080768..2084863]: 6024384..6028479   0 (6024384..6028479)  4096
 999: [2084864..2086911]: 6091968..6094015   0 (6091968..6094015)  2048
1000: [2086912..2088959]: 6048960..6051007   0 (6048960..6051007)  2048
1001: [2088960..2095103]: 6032576..6038719   0 (6032576..6038719)  6144

これはひどいレベルですね。もうありえない感じじゃないでしょうか。

# time cat /data/test1g_D > /dev/null

real    0m16.378s
user    0m0.023s
sys     0m0.456s

16.378秒。かなり遅くなってきました。

パターンE

# xfs_bmap -v /data/test1g_E
/data/test1g_E:
 EXT: FILE-OFFSET         BLOCK-RANGE       AG AG-OFFSET          TOTAL
   0: [0..7]:             4001000..4001007   0 (4001000..4001007)     8
   1: [8..15]:            2769576..2769583   0 (2769576..2769583)     8
   2: [16..23]:           3351192..3351199   0 (3351192..3351199)     8
   3: [24..31]:           3998048..3998055   0 (3998048..3998055)     8
   4: [32..39]:           2470088..2470095   0 (2470088..2470095)     8
   5: [40..47]:           2837536..2837543   0 (2837536..2837543)     8
   6: [48..55]:           2748600..2748607   0 (2748600..2748607)     8
   7: [56..63]:           2988880..2988887   0 (2988880..2988887)     8
   8: [64..71]:           3451752..3451759   0 (3451752..3451759)     8
   9: [72..79]:           3476944..3476951   0 (3476944..3476951)     8
  10: [80..87]:           hole                                        8

・・・・・省略・・・・・

261017: [2097064..2097071]: 46368..46375       0 (46368..46375)         8
261018: [2097072..2097079]: 3089136..3089143   0 (3089136..3089143)     8
261019: [2097080..2097087]: 2496016..2496023   0 (2496016..2496023)     8
261020: [2097088..2097095]: 3360472..3360479   0 (3360472..3360479)     8
261021: [2097096..2097103]: 3373552..3373559   0 (3373552..3373559)     8
261022: [2097104..2097111]: 3616384..3616391   0 (3616384..3616391)     8
261023: [2097112..2097119]: 3894400..3894407   0 (3894400..3894407)     8
261024: [2097120..2097127]: 2744288..2744295   0 (2744288..2744295)     8
261025: [2097128..2097135]: 2427728..2427735   0 (2427728..2427735)     8
261026: [2097136..2097143]: 3962440..3962447   0 (3962440..3962447)     8

これは、まずありえなさそうな状況ですが、、、このファイルを作るのも苦労しました(コンピュータが時間をかけて頑張ってくれました)w

# time cat /data/test1g_E > /dev/null

real    2m39.257s
user    0m0.012s
sys     0m1.291s

ぬお、2分39.257秒と、ここまで来るともう実用できない感じですね。
でも、こんな状態になるケースが・・・。

まとめ

ということで、今日はxfsファイルシステムのデフラグ方法を学びました!
多少はエクステントが分割していようが、シーケンシャルアクセスだとそれほど影響がでないことがわかりました。
それでは! =͟͟͞͞(๑•̀=͟͟͞͞(๑•̀д•́=͟͟͞͞(๑•̀д•́๑)=͟͟͞͞(๑•̀д•́


Linuxカーネル Hacks ―パフォーマンス改善、開発効率向上、省電力化のためのテクニック

Linuxカーネル Hacks ―パフォーマンス改善、開発効率向上、省電力化のためのテクニック