Windows 秘話: ディスク上のサイズの正体
フォルダーのサイズを確認するときに表示される統計データは、一体どこから取得されるのでしょうか。
Raymond Chen
フォルダーを右クリックしてプロパティを確認すると、プロパティ ダイアログ ボックスには、"サイズ" および "ディスク上のサイズ" という 2 つの値が表示されます。これらの値には、一体どのような意味があって、何を測定した値なのでしょうか。
フォルダーのプロパティ ダイアログ ボックスでは、すべてのファイルについて、単純に再帰的なディレクトリ検索を実行します。ハード リンクを使用して、同じ基盤となるファイルを参照しているファイル名をフィルター処理することはありません。また、再帰的なディレクトリ検索では、アクセス許可がないサブディレクトリがスキップされるため、このサブディレクトリにあるファイルは、フォルダー サイズの合計には含まれません。
つまり、再帰的なディレクトリ検索には、ある程度のインテリジェンスが備わっています。明示的に用意されているインテリジェンスもあります。たとえば、再解析ポイントを検出すると、この再解析ポイントでは再帰処理は実行されません。また、偶発的に備わっているインテリジェンスもあります。たとえば、ファイルへのシンボリック リンクのサイズは 0 と見なされます。これは、ディレクトリ検索のコードで、ファイルを十分に確認できるからではなく、シンボリック リンクのディレクトリ エントリのサイズが 0 と報告されるからです。サイズの合計に含まれるファイルについて説明したので、今度は、これらの数値がどのように算出されているのかを説明しましょう。
サイズについて
サイズは簡単に測定できます。WIN32_FIND_DATA.nFileSizeLow および nFileSizeHigh の FindFirstFile 関数によって報告されたものをファイル サイズとして集計します。念のためお伝えしておきますが、NTFS ファイル システムでディレクトリ エントリを更新する方法により、この値は必ずしも正確であるとは限りません。詳細については、また別の機会に取り上げますが、簡単に言うと、書き込み中のファイルは、ファイル ハンドルを閉じるまで、正確なファイル サイズが報告されない可能性があります。また、ファイル ハンドルが閉じられた後でも、ファイルを開くために使用するディレクトリ エントリしか更新されません。
ディスク上のサイズを測定するのは、さらに複雑です。ドライブで圧縮がサポートされており (GetVolumeInformation 関数から FILE_FILE_COMPRESSION フラグが返されます)、ファイルが圧縮されているかスパース ファイルの場合 (FILE_ATTRIBUTE_COMPRESSED または FILE_ATTRIBUTE_SPARSE_FILE が返されます)、ファイルのディスク上のサイズは GetCompressedFileSize 関数によって報告される値になります。この関数では、ファイルの圧縮されたサイズ (圧縮されている場合)、またはファイル サイズからデコミットされたり論理的にサイズが 0 として扱われたりする部分を引いたサイズ (スパース ファイルの場合) が報告されます。圧縮されたファイルでもスパース ファイルでもない場合、ディスク上のサイズは、FindFirstFile 関数により最も近いクラスターに切り上げて報告されるファイル サイズになります。
元々、ディスク上のサイズのアルゴリズムは、Windows 95 チームが開発したもので、ファイル システムに対する見方は、MS-DOS 寄りのものでした。また、当時は、FAT が唯一のディスク ファイル システムで、ハード リンク、代替データ ストリームなどのようなものは存在せず、ファイル コンテンツはクラスター単位で格納されていました。
このような前提は NTFS には当てはまりません。"ファイル コンテンツはクラスター単位で格納される" という点すら当てはまりません。NTFS では、実際のところ、マスター ファイル テーブル (MFT) のスラック スペースにファイルを格納することで、クラスターを使用せずにファイルのデータを格納できます (詳細については、「The Four Stages of NTFS File Growth (NTFS ファイルに関する 4 段階の発展、英語)」を参照してください)。
当然ながら、ディスク上のサイズのアルゴリズムでは、ファイル名自体が占有するディスク領域、ディレクトリ エントリの情報、ファイルのメタデータ、代替データ ストリームなど、他のファイル システムのオーバーヘッドは考慮していません。
"サイズ" と "ディスク上のサイズ" の値は、ディスクの空き領域に対する特定のディレクトリのサイズをバイト単位で計算した値ではなく、ほとんどのファイルにそれほど多様性がないという前提に基づいた大まかな見積もりに過ぎません。つまり、ハード リンクは存在せず、代替データ ストリームはほとんど使用しないという前提で算出した値です。Windows ディレクトリなど、多数のハード リンクを含むディレクトリがある場合、見当違いな値が表示されます。
ディスク上のサイズを使用して、ディレクトリの大まかなサイズを把握することは可能ですが、これが単純な計算に基づいた値であることは覚えておいてください。ディスクの使用領域を注意深く監視する必要がある場合は、ディスクの使用領域を適切に追跡できるディスク クォータなどの機能を使用することをお勧めします。
Raymond Chen は、自分の Web サイト「The Old New Thing」および同じタイトルの書籍 (Addison-Wesley、2007 年) で、Windows の歴史、Win32 プログラミング、そして 3 歳児に冗談を言うことについて扱っています。