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秒と、ここまで来るともう実用できない感じですね。
でも、こんな状態になるケースが・・・。