WSLパッケージの2.0.0にていくつか機能追加が行われました。ここでは仮想ディスクの圧縮を試してみます。
VHDX肥大化の課題
仮想マシンを利用するLinuxサブシステム(WSL2)はHyper-Vをベースとしているため、ファイルシステムもVHD(VHDX)を利用します。VHDは仮想ディスクをWindowsが管理するファイルとして提供する仕組みです。
WSL2が利用するVHDXは使用量に応じて伸長する仕組みですが、よく話題に上がるのがLinux上でファイルを削除してもWindows側では空きが増えない(=VHDXファイルのサイズが縮まない)という状況です。
Optimize-VHDやdiskpartというコマンドを用いてVHDXを圧縮するtipsが紹介されていましたが、今回はWSLの機能としての提供です。
公式ドキュメントによると、この機能を使う方法が二つ示され ています。
一つは.wslconfigに以下のように記述します。
[external]
sparseVhd=true
このキーをtrueに設定すると、新しく作られるVHDは自動でsparseに設定されます?
つまり、この方法では既にあるVHDXには影響がない?
もう一つの方法はディストロを指定して設定します。
PS C:\> wsl --manage <distro> --set-sparse <true/false>
なるほど、既存の場合にはこちらを使うのですね。
これで自動的にサイズがシュリンクされるらしいのですが、、、、いつ?
設定してみましたが、いつまでたってもVHDXのサイズが変わらないなーと思ったのは私だけではないはずです。
そもそもすぱーすってなに?
Microsoftのドキュメントにスパースファイルの説明があります。
ファイル中のゼロが連続するデータのことをスパースデータセットと呼ぶそうです。こういうファイルは圧縮すればサイズが縮むものの圧縮ファイルシステムではパフォーマンスが大きく下がってしまうので、スパースファイルというものが導入されたとのことです。
なるほど、WSLの新機能としてはVHDXにスパースを適用するだけで仕組みとしてはNTFSの機能なのですね。
スパース自体はWindows2000のNTFS3.0でサポートされた機能なので、もう20年以上も歴史のある機能なのですね。仮想ファイルシステム自体を操作するものなので少し怖かったのですが、枯れた機能であれば安心して使えそうです。
実際小さくなってる?
スパースはファイルそのものに操作を加えるわけではなく実占有領域を節約する仕組みのようです。そこでエクスプーラーからディスク上のサイズ
を確認するとしっかり小さくなっていました。
ただ、この仕組み自体はNTFSで連続する0を端折る機能なので単純にLinux上のファイルを消しただけでは効果はなさそうです。trimを実行するなり空き領域をゼロ埋めするなりという作業は必要でしょう。
具体的にはこんな操作です。
$ fstrim /
ただ、なんとなく使っている人には fstrim を実行するだけでもハードルの高い作業になってしまうので、お手軽さを標榜するには自動化が必須かもしれません。この機能もまだexperimentalなので今後の動きに注目ですね。
fsutil.exe
さて、このスパースですが昔からある機能だとすると、wslコマンドでなくてもコントロールできるはずです。fsutil.exeというツールで操作するようです。
PS C:\> fsutil sparse
---- サポートされる SPARSE コマンド ----
queryFlag スパースの照会
queryRange 範囲の照会
setFlag スパースに設定
setRange スパース範囲の設定
wsl.exeからは on/off の設定のみでしたが、このコマンドを使えば現在の状態が確認できるようです。
スパースは昔からあるけどHyper-V的には新対応?
WSLが対応したのならとHyper-Vで使用するVHDXにもfsutilを使ってスパースを設定したところ、エラーが出てマウントできませんでした。WSLのベースはHyper-Vなので何等か回避方法があるのだと思います。例えばスパース範囲の設定でスーパーブロックを回避すれば良い等。。。想像ですけど。いずれにせよ細かいルールが不明なのでこの機能にどのくらいリスクが残されているかは不明です。今のところ致命的な障害は無さそうですが、experimentalが取れてから使った方が安心な機能のような気がします。