未使用のメモリーをホスト側に還元可能に
「Build 19013」の「WSL 2」ではメモリーの使用効率が改善され、「WSL 2」の使い勝手が向上しています。仮想マシンとメモリーの確保
ご存知の通り「WSL 2」は仮想マシン上で動作します。「Linux kernel」や「WSL 2」上で動作するLinuxアプリケーション(ワークフロー)の求めに応じ、仮想マシンが必要とするメモリーが増加する時、ホストからより多くのメモリーが確保され、仮想マシンの全体的なメモリー使用量は増加します。
使い終わって未使用になったメモリー
ワークフローにより確保されたメモリーは、ワークフローが終了すると未使用のメモリーとなりますが、その未使用になったメモリーはホスト側に還元されません。しかし「Build 19013」ではメモリー管理が改良され、もう不要になった未使用のメモリーはホスト側に通知できるようになり、仮想マシンが使用するメモリー使用量を減らせるようになりました。
つまりLinuxプロセスが使用していたメモリーが解放され未使用になると、それらのメモリーはホスト側に返され、ホスト側のメモリー使用量が減ることになります。
テスト
単純なLinuxアプリを用いて、メモリー使用量の変化を見てみましょう。ソースコード
以下のCソースコードからアプリをビルドし、このアプリの実行前と実行後のメモリー使用量の変化を見てみましょう。メモリーをヒープから3GB確保するアプリです。
#include <stdlib.h> #include <stdio.h> int main() { int i = 0; char* buffer = (char*) calloc(3000000000,1); printf("Done allocating\n"); scanf("%d",&i); free(buffer); return 0; }
メモリー使用量の計測方法
「Windows」側で使用されるメモリーは、「WSL 2」の仮想マシンに対応する「Vmmem」プロセスを監視することで計測します。「Linux」側で使用されるメモリーは、「free -h」コマンドで出力される「Used Memory」と「Cached Memory」を確認することで計測します。
1.アプリ実行前
アプリ実行前のメモリー使用量は、以下のようになっています。項目 | メモリー使用量 |
---|---|
Vmmem | 316.0MB |
Used Memory | 57M |
Cached Memory | 33M |
2.アプリ実行時
アプリを実行すると多くのメモリーが要求され、Linuxが使用するメモリー使用量が増加します。そのため「Vmmem」のメモリー使用量も増加します。
項目 | メモリー使用量 |
---|---|
Vmmem | 3,194.0MB |
Used Memory | 2.9G |
Cached Memory | 55M |
3.アプリ実行後
アプリが終了し使用したメモリーが解放されると、そのメモリーがホスト側に還元されます。そのため「Vmmem」のメモリー使用量が低下します。
項目 | メモリー使用量 |
---|---|
Vmmem | 334.0MB |
Used Memory | 58M |
Cached Memory | 55M |
キャッシュメモリーについて
Linuxの仮想マシン内で使用するメモリーは、ユーザーのプロセスだけではありません。「Linux kernel」は多くのキャッシュを使用しており、これらのキャッシュ中にはファイルシステムのパフォーマンスを改善するためファイルの中身をキャッシュしているページキャッシュも含まれています。
テスト
データベースやNodeJSサーバーを起動するサンプルコンテナーアプリを使用し、このキャッシュメモリーの変化を見てみましょう。コンテナーの操作は「docker-compose」で行っています。
ソースコードは以下で参照できます。
イメージの構築とコンテナーの実行後
イメージの構築とコンテナーを実行した後、メモリー使用量は以下のようになっています。項目 | メモリー使用量 |
---|---|
Vmmem | 2,265.8MB |
Used Memory | 65M |
Cached Memory | 1.7G |
Linuxのメモリー使用量はたかが65Mですが、「Vmmem」のメモリー使用量は2GBになっており、非常に大きな乖離が見て取れます。
イメージの構築とコンテナーの実行過程において、非常に多くの様々なファイルにアクセスし、ページキャッシュが1.7GBのサイズになったためです。
キャッシュを解放するまでメモリー使用量は減らない
「Linux kernel」がページキャッシュを解放するまで、「Vmmem」のメモリー使用量は減りません。これはページキャッシュによるパフォーマンスの改善を活用するためであり、意図した設計です。
ページキャッシュを解放するには
「Linux kernel」が使用しているページキャッシュを解放には、以下のコマンドを「root」で実行します。
echo 1 > /proc/sys/vm/drop_caches
このコマンドの実行によりページキャッシュが解放されれば、「Vmmem」のメモリー使用量が減り、その分「Windows」側に戻されることになります。
もちろんターミナルを閉じてLinuxを終了することでページキャッシュを解放することも可能です。
どのようにこの機能を実現したか
今回のメモリー管理の改善で行われた内容の紹介です。Linux kernelにパッチ
小さく連続したメモリーブロックがLinux側で不要になった時にそれらをホストマシンに返せるよう、「Linux kernel」にパッチがあてられています。また「WSL 2」向けの 「Linux kernel」は上記のパッチが含まれるよう、アップデートされています。
さらに「Hyper-V」で今回の改良をサポートできるように、修正も加えられています。
可能な限り多くのメモリー還元できるように
可能な限り多くのメモリーをホスト側に還元できるようにするため、定期的に未使用のメモリーが連続したブロックに配置されるように調整が行われます。この調整はCPUがアイドルの時にのみ実施されます。
この機能が実行されると、「dmesg」コマンドで出力されるメッセージに以下のメッセージが含まれます。
WSL2: Performing memory compaction
手動でこの機能を実行するには、「root」で以下のコマンドを実行します。
echo 1 > /proc/sys/vm/compact_memory
機能の設定
今回実装されたメモリー管理の機能は、「.wslconfig」ファイルで振る舞いを制御することができます。
[wsl2]
pageReporting = <bool> # Enable or disable the free memory page reporting feature (default true).
idleThreshold = <integer> # Set the idle threshold for memory compaction, 0 disables the feature (default 1).
pageReporting = <bool> # Enable or disable the free memory page reporting feature (default true).
idleThreshold = <integer> # Set the idle threshold for memory compaction, 0 disables the feature (default 1).