メモリを消費できる仕様のWSL2

前回、WindowsでLinuxコマンドを実行する方法として「WSL2」と「MSYS2」を使う場合の違いを紹介した。前回紹介したのは消費メモリの差だ。WSL2自体はそれほどメモリを消費しないのだが、WSL2でUbuntuを使っていると徐々に消費メモリが増加していき、いずれはシステムのメモリを使い切ってしまう。使い方にもよるのだが、特にディスクアクセスを伴うような使い方をしていると早めに消費される。

これはLinuxカーネル的には当然の動作であり、Windows側の消費メモリが上限に達しただけだ。この挙動への対処は結構難しい。Windows側を優先して使用できるメモリを制限すればWSL2での性能が落ちるし、逆に今のままにしておくとWindows側でメモリ不足が発生する可能性を残すことになる。どっちをとるかという問題になるわけだが、この点に関してはMicrosoftが今後どういった方針を出してくるかによるので注目したい。

パフォーマンスを引き上げるためのディスクキャッシュ

ストレージデバイスがSSDへ置き換わったことで、ディスクアクセスは高速になった。しかし、それでもCPU内部でのアクセス速度や、CPUからメモリへのアクセス速度と比べると、CPUからディスクへのアクセス速度はすごく遅い。ディスクアクセスが発生するほどに処理が遅くなる。

こうした挙動を改善してパフォーマンスを引き上げるために、LinuxをはじめUNIX系のOSはディスクアクセスをキャッシュする機能を備えている。つまり、メモリに読み込んだデータはメモリ上にキャッシュしておき、次に同じデータへアクセスがあった場合、ディスクにアクセスするのではなく、メモリにキャッシュされているデータからデータを取得して返すようになる。こうすると処理速度がディスクレベルからメモリレベルへと変わるため、とても速く動くようになる。

UNIX系のOSはシステム全体でパフォーマンスを最大化するために、メモリに余剰が見られると、可能な限りディスクキャッシュを作ろうとする。これはデフォルトの挙動であり、LinuxをはじめUNIX系OSの多くがこうした挙動をとる。

ディスクキャッシュとその効果については、簡単な方法で調べることができる。まず、次のように5GBのファイルを作成する。

daichi@XPS-13-9305:~$ dd if=/dev/random of=data.raw bs=1024x1024 count=1024x5
5120+0 レコード入力
5120+0 レコード出力
5368709120 bytes (5.4 GB, 5.0 GiB) copied, 63.3702 s, 84.7 MB/s
daichi@XPS-13-9305:~$

◆作成された5GBのファイル

daichi@XPS-13-9305:~$ ls -l data.raw
-rw-r--r-- 1 daichi daichi 5368709120 10月 20 10:57 data.raw
daichi@XPS-13-9305:~$

手元で同じ実験をする場合、Windows側の残りメモリの8割ほどのサイズを上限としてファイルを作成してみてほしい。その場合、ファイルが全てキャッシュに乗るのでディスクキャッシュの効果を体験しやすい。

このファイルをただcatコマンドで取り出して/dev/nullへ捨てる処理を実行する。ここでは、次のように処理に4.4秒ほどかかっている。

daichi@XPS-13-9305:~$ time cat data.raw > /dev/null

real    0m4.364s
user    0m0.000s
sys     0m1.114s
daichi@XPS-13-9305:~$

Linuxカーネルはこの処理でファイルを全てディスクキャッシュに乗せる。つまり、次にこのファイルにアクセスしたときには、ディスクからではなくメモリからのアクセスが行われることになる。先ほどと同じくcatコマンドを実行してみよう。

daichi@XPS-13-9305:~$ time cat data.raw > /dev/null

real    0m0.466s
user    0m0.000s
sys     0m0.466s
daichi@XPS-13-9305:~$

今度は0.46秒ほどで処理が完了している。処理速度はキャッシュ後に9.36倍だ。これがディスクキャッシュの効果である。

時間 速度比率
キャッシュ前 4.364s
キャッシュ後 0.466s 9.36倍

Linuxカーネルはこのパフォーマンスを得るために可能な限りディスクキャッシュを利用しようとする。これがWindows側から見れば、WSL2によるメモリの大量消費というかたちで見えてくる。

では、このコマンドを実行しているときのWindows側の動きを見てみよう。タスクマネジャーでメモリの消費をモニタリングするとわかりやすい。WSL2を起動した段階で多少メモリが消費され、catコマンドでデータにアクセスした段階から4.4秒ほどかけて一気にメモリを消費している。Linuxカーネルが作成したディスクキャッシュがこのメモリの消費として表れている。

実験中のWindows側のメモリ消費のようす

そしてこのメモリ消費は、「wsl —shutdown」でWSL2を完全に終了するまで継続する。

WSL2をシャットダウンするとメモリが解消される

ほぼ10倍というのはなかなか魅力的なパフォーマンスの向上だ。可能な限りディスクキャッシュを使おうとするのは、カーネルの基本戦略としては悪くない。

メモリが潤沢ならWSL2、扱う総ファイルサイズが小さいならWSL2

ということは逆に、メモリが潤沢にあるPCであれば、WSL2のメモリ消費の問題はそれほど問題にはならない。WindowsとLinuxを同時にかなりアグレッシブに活用していくのであれば、メモリが潤沢なPCを選ぶのが良いということになる。

また、Linuxは使うもののディスクはそれほど使わないという場合も、WLS2で十分な恩恵を受けることができる。このように一見すると似たような技術でも、動作を知っているとどういったケースでどの技術を使えば良いかはおのずと見えてくるものだ。