MFTの最適化

Windows XP上に18GBもある仮想マシンの仮想ディスクをフラグメンテーションなく配置する(「仮想ディスクとデフラグ」)という作業を発端として、デフラグ後にMFTに整合性がなくなるという事態が発生して(「MFTが壊れた」)、色々と調べたらMFT Zoneという不思議な領域があることを知った。さらに調べるとXPに標準でバンドルされているデフラグツールが、このMFT Zoneを破壊してしまうという現象があることがわかった。そこで、標準デフラグツールを使ってもMFTにフラグメントを起こさないで快適に使う方法を考えてみた。

なお、ネット上の多くのページでMFTとMFT予約領域が曖昧に書かれているケースが見受けられた。MFT予約領域は「将来MFTとして使われる領域」なので、ここを幾ら多めに予約したところで、肝心のMFT自身が過度にフラグメントしてはパフォーマンスが低下してしまう筈だ。(MFTが過度にフラグメントした状態でどの程度パフォーマンスが低下するかは未測定。)

ちなみに、以下の記述はマイクロソフトの技術文献をみて書いているわけではなく、デフラグツールなどの振る舞いからの類推なので、間違った点を含む可能性がある。

MFTのおさらい

インストールしたてやバックアップからのリストア直後などはMFTの実体(C:\$MFT という隠しファイル)に、隣接(HDDの配置上すぐ後に)して、MFTの予約領域(MFT Zone)が割り当てられるらしい。マイクロソフトによるとMFT Zoneはボリュームの12.5%が割り当てられるというので、70GBのボリュームだと8.75GBになる。ファイル一つ一つに対して$MFTに1エントリ(1KB+α)が記録される(つまりUNIXのiノードに相当するものだろうか)ので、ファイルの数が増えるに従って$MFTの大きさも成長する。$MFTはファイルへのアクセスの際にポインタとなるので、$MFTファイル自身がやたらとフラグメントを起こすと性能が劣化するらしい。そのために$MFTに隣接してMFT Zoneという予約エリアが設けられていて、$MFTを拡大する必要が出てくると、そのZoneを使って成長して行く。しかし、そのPCにどれくらいのファイルが格納されるか分からないので、MFT Zoneはあくまで予約領域であり、その扱いは「HDDの空き領域の一部」として一般ファイルの格納領域がなくなるとMFT Zoneを侵食して使い始める。MFT Zoneは次のようなアルゴリズムで一般ファイルに開放するらしい(デフラグツールの画面を観察した結果の推測)。

  1. $MFTとそれに続くMFT ZoneはHDDの先頭(右側)付近に割り当てられ、HDDの後方(左側)に十分な空き領域がある。ファイルが作られるとファイルの本体は空き領域に格納されてゆき、$MFTも必要に応じてMFT Zoneを使って成長する。
  2. ファイルを格納するためのHDD後方の空き領域がなくなると、MFT Zoneとして予約されていた領域の後半半分を空き領域として開放して、そこにファイルが格納されて行く。
  3. さらにその空き領域も使い果たすと、MFT Zoneをまた半分に分割して、後半部分を空き領域として開放する。
  4. 最終的には、MFT Zoneを$MFTと一般のファイルが取り合い、バランスがとれてHDDを使い果たす。従って、当初何GBもあった不思議な空間は最後になくなり、めでたし、めでたしとなる。

ところが、デフラグツールは、まだ一般ファイルに割り当てることができるHDDの空きスペースがあるにもかかわらず、MFT Zoneを潰してしまう(MFT Zone(=HDDの前方)へファイルを詰め込んでしまう)ことがある。(少なくともWindows XPに標準でバンドルされているデフラグツールではこの様な現象が起きた。)しかも、いきなり$MFTの隣接するエリア、つまりMFT Zoneの先頭から埋めていく。この状態で$MFTのエントリ数以上のファイルがHDDに置かれると$MFTはフラグメンテーションを起こすしかなく、これを繰り返すと、(一般のファイルはデフラグされていても)$MFTはフラグメントを起こしているので性能が悪くなる、と予想できる。Windows標準のデフラグツールでは、$MFTの本体部分はデフラグの対象としていないようだ。逆に、フラグメントしてしまった細かい$MFTの一部は集めてくれるが、本体部分とはかけ離れた、とんでもないところ(HDDの後ろ側とか)に配置してしまう。(デフラグツールによってはMFT Zoneを潰さないものや、$MFTをデフラグの対象とするものもあるかも知れないが、ここでWindowsにバンドルされている標準デフラグツールを前提に話をする。)

ということは、デフラグをしない方が良いのかというと、それでは一般のファイルがフラグメントを起こし、性能が劣化する。では、デフラグツールを使いつつ、$MFTをフラグメントさせない方法はないのか?

MFTファイルとして領域を確保する

$MFTが成長するMFT Zoneを「HDDの空き領域の一部」としてエリアを確保するのではなく、最初に$MFTファイルとして十分な大きさに成長させてしまい、$MFTファイルとして領域を確保してしまう、という方法はどうだろう。

つまり初期の、$MFTに隣接してMFT Zoneが存在し、$MFTがフラグメント無に成長できる状態にある内に、$MFTを成長させてしまう。一旦、大きくなった$MFTは一般ファイルが消去され、そのファイルのエントリが利用されなくなっても、将来、別のファイルで再利用するために確保してあり、$MFT自身は縮小されない。フラグメント無しで成長しきった$MFTは将来フラグメント起こすことが無い。(市販やフリーのデフラグツールで$MFTをイジった場合は別だが、Windowsにバンドルのデフラグツールでは無いようである。今のところの観察では。)

では、どのように$MFTを成長させるのか。一般ファイルをある程度の数になるまで生成もしくはコピーすればいい。ただし、そのPCが将来格納するであろうファイル群の「平均サイズ」と、そのサイズでHDDが一杯になるファイル数まで埋めていく必要がある。例えば、極端な例では、1つ数十GBの仮想ディスクを幾つか格納する場合と、たがだか数MBの写真や音楽を多く可能する場合では、HDD上のファイル数も大きく異なる。そのPCをどの様な目的で使い、その場合の平均ファイルサイズがどれ位か予想して、そのサイズのファイルで埋め尽くすのが理想的だが、それも難しい。実質的にはある程度ファイル数を大目(ファイルのサイズを小さめ目)に見積もって$MFTを確保すればいい。(もし、平均ファイルが大きくなった場合は$MFTのエントリが使われないだけだから。)例として、C:\Program Filesを丸ごと、適当な作業用ディレクトリへ複数コピーして空き領域を消費するなどの方法がある。(インストールしたてでC:\Program Filesの下が殆ど空の場合は、C:\Windowsなど適当なディレクトリを作業用ディレクトリに複数コピーすればいい。)

あと、一点注意が必要なのは、完全に埋め尽くそうとすると、一番最後に$MFTと一般ファイルが残った僅かのエリアを取り合って、$MFTがフラグメントを起こすことがある。この数クラスタのゴミの様なフラグメントがデフラグツールにより離れた場所に移動されることがある。そこで、HDDを一杯まで埋めるのではなく、適当な数のファイルのコピーで押さえておくか、数十MBか数百MBを残したところで終わらせば、大体の目的は達成できる。

実際にこの方法を使った状況を見てみる。

先ずはバックアップツールを使ってHDDをコピーしてしてきた状態。(バックアップツールには以前使っていたStandbyCopyというソフトを使用。)

少々、フラグメントを起こしているが、ほぼデフラグされた状態で配置されている。MFT Zoneはこの段階では一般のファイルと認識されている。(Windows標準のデフラグツールだと、MFT Zoneは「一般ファイル」と認識されたり「空き領域」と認識されたりして、表示が不安定。)

HDViewというフリーのHDD解析ソフトを使って表示。

HDViewは右側部分に全体の様子、左側部分が一部の拡大画面となっている。右側の全体画面では上がHDDの先頭(=外周、デフラグツールの左側)、下が後方(=内週、デフラグツールの右側)に相当する。黄色い部分がC:\$MFTファイル、オレンジ色がMFT Zoneである。HDViewでみるといくつかのファイルがフラグメントを起こしているが、HDViewではファイルのデータ本体がひとまとまりでも、属性データなどが連続していないとフラグメント状態として表示されるらしい。

HDViewでC:\$MFTファイルの情報を表示させたところ。

同様にWindows標準のデフラグツールで全ファイルの情報とMFTの情報を表示したところ。


この情報から分かるとおり、現在のファイル数の合計は98,472、平均ファイルサイズは666KBである。一方、MFTのエントリ数はファイル数にディレクトリ数を加えた110,990であり、ほぼエントリの99%が利用中である。つまり、この状態でファイルが増えると$MFTも直ぐに拡大してしまう。現在の空き領域の大きさは、

約22GBが空きの状態である。平均ファイルサイズが666KBなので、単純計算ではあと3万3千個のファイルが生成させる可能性があることになるが、18GBの巨大仮想ディスクファイルがあるので、これは異常値として取り除く。実効的な平均ファイルサイズは約440KBとなり、これで残りの空き領域22GBを使うと、約5万個のファイルを生成することができる。また、もし18GBのファイルがなければ、約9万個になり、現在の2倍のファイル数になる。(75.5GBの内、現在約半分の40GBを使っているので、あと生成できるファイルは現在と大体同じなので、理屈に合う。)MFTのエントリの数(=最大ファイル数)は多めに取っておいた方が良いので、とりあえず、あと10万個を目処にダミー・ファイルを生成する。

10万個のファイルを生成してもボリュームを満杯にしてしまわない様に、まず、数バイトの小さなファイルを倍々でコピーして約4万個、それに大きめのファイルも含めたC:\Program Filesを丸ごとコピーして約6万個、合計で約10万個強のファイルを生成した。ファイル数は現在のものと合計で206,086で、現在の約倍の数のファイルとなった。(ファイルをコピーするのではなく、コマンドプロンプトで適当なディレクトリを作成して“for /l %i in (1,1,65536) do @copy nul: a%i”で空のファイルを作る方法の方がベターだろう。)

この状態でのファイルの配置状況は以下のとおりとなった。

MFTのエントリ数も次のように223,531となり、$MFTのサイズも218MBとなる。

HDViewで確認しても、$MFTが成長したが、まだMFT Zoneに隣接している。(黄色い部分とオレンジ色の部分が隣接している。)

念のためHDViewで$MFTの情報を表示したが、データ本体部分はフラグメントを起こさず連続領域に割り当てられている。

さて、この状態で先ほどコピーしたダミーのファイルをすべて削除する。すると、ファイルの配置は最初の状態になる。

しかし、次の通り、$MFTのサイズは218MBのままである。

$MFTの中には約11万個のエントリが存在しているが、ファイルを削除したので約49%のエントリしか使っていない。残りは、将来、ファイルが生成去れた時に再割り当てされる。

デフラグしてみる

バックアップソフトでコピーした状態ではそれほどフラグメントは起していなかったが、デフラグを1回かけてみた。勿論、Windows XPにバンドルされている標準のデフラグツールを使って。

大分すっきりした。デフラグできなかったのは2つだけだった。が!、何気にDHViewで見てみると、

C:\$MFT(黄色い部分)とMFT Zone(オレンジ色の部分)の間に青い帯が。拡大してみると、

$MFTに隣接している筈のMFT Zoneへ、すでに一般のファイルで詰められている。しかもMFT Zoneが“フラグメント”している!(HDViewの拡大画面にある青い部分に点在しているオレンジの部分。)さすがはWindows標準のデフラグである。初回からやってくれる。(よく、こんなソフトを標準で搭載しているなぁ、と疑問である。) しかし、すでに$MFTは拡張済みなので気にしない。いっそのことMFT Zone全体にファイルと詰め込んでもらっても構わなかった。

追記(2008/06/12)

もう一台、仮想マシンをコピーしたり削除したりして(=つまり大きなファイルを作ったり消したりした後)、1週間くらいしてデフラグしてみた。今度は....

MFT Zoneは全部一般ファイルで埋め尽くされたか!と思ったら、

なんと$MFT(黄色い部分)に隣接してMFT Zone(オレンジの部分)が配置されている。以前あったMFT Zoneから比べれば僅かだが(たぶん100MB程度)、確かに$MFTに再び隣接して配置されている。以前は一般ファイルが間に割り込んでいたのに。Windows(というよりはWindowsに付属のデフラグツール)は全くよく分からない。(ひょっとするとHDViewの表示がおかしかったのかも知れないが.....)