WSL2では、割り当てるメモリやCPU数などの設定を行うことができる。この設定は、WSL2を実行している「軽量ユーティリティ仮想マシン」の設定である。設定はユーザーのホームディレクトリの下にある「%userprofile%\.wslconfig」ファイルで行う。本記事では、これを.wslconfig(あるいは.wslconfigファイル)と表記する。
なお、WSLの基本的なことに関しては、以下の記事を参照されたい。
・Windows Subsystem for Linuxガイド 第1回 基本編
https://news.mynavi.jp/article/20211203-2211548/
・Windows Subsystem for Linuxガイド 第2回 コマンド編
https://news.mynavi.jp/article/20211228-2240002/
WSL2の設定前に必要なこと
設定を行う場合、すべてのWSLディストリビューションを停止させ、軽量ユーティリティ仮想マシンを停止させる必要がある。ディストリビューションの動作状態の確認には「wsl.exe -l -v」が利用でき、軽量ユーティリティ仮想マシン自体の終了には、シャットダウンオプション「wsl.exe --shutdown」を使う。
シャットダウンする場合には注意する点がある。WSLディストリビューションが動作中にシャットダウンすると、実行中のbashなどのLinuxアプリケーションは、終了処理を行うことができない。bashは、終了時にコマンドラインの履歴をファイルに保存しているが、こうした処理が行われなくなる。基本的にはシャットダウンオプションを使う前に端末セッションからexitを使ってセッションを終了させる。
.wslconfigファイルの構造
.wslconfigファイルは、テキストベースで、(図01)のような構造をしている。中身は行単位となり、セクション行と設定行、注釈行の3種類がある。
セクション行は、設定をカテゴリ分けするための行で、角括弧("["と"]")で囲まれたテキストからなる。.wslconfigでは"[wsl2]"セクションのみが有効だ。
設定行は、
設定名 = 設定値
という形式の行で、1行で1つの設定項目に対応する。.wslconfigには(表01)のような設定名がある。行の先頭を"#"にすると注釈行となり、設定としては意味を持たない行となる。
.wslconfigのすべての設定項目には、デフォルト値が定義されており、何も指定を行わなければWSL2(軽量ユーティリティ仮想マシン)は、デフォルト値を使って起動する。もし、.wslconfigファイル自体が存在しない場合、すべてデフォルト値となる。逆にいうと、.wslconfigファイルでは、デフォルト値と異なる設定のみ記述すればよい。
このファイルは、Win32側にあり、ファイルの形式もWindowsのテキストファイル(ANSI、CR-LF)に準ずる。
WSLは、.wslconfigファイルのエラーを表示しない。テキストファイルであるため、綴り間違い(複数形のsがないなど)も起こりやすい。設定後にLinux側で指定が有効なのかを確認する必要がある。
設定と確認方法
ここでは、設定項目ごとに設定の具体例やその確認方法を解説する。
カーネル関連の設定項目
カーネル関連の設定項目には"kernel"と"kernelCommandLine"、“debugConsole”がある(表02)。前者は、ユーザーがコンパイルしたカーネルを利用する場合にそのパス(vmlinuxの場所)を指定するもので、後者は、カーネル起動時のコマンドラインオプションを指定するものだ。どちらも標準では指定が不要だ。
kernelは、以下のようにvmlinuxファイルの位置を指定する。なお、Windowsのパス区切りである“\”は、.wslconfigファイルではエスケープ文字となるため、“\\”と指定する必要がある。
kernel = C:\\Temp\\WSL2NewKernel\\vmlinux
kernelCommandLineは、実際のコマンドライン同様にオプションなどをスペースで区切って指定する。
kernelCommandLine = debug nosmp
この設定の確認方法だが、kernelに関しては、Linuxのunameを使う。このコマンドは、カーネルに関する情報などを表示するもので、「uname -a」とすることで、カーネルのバージョンや作成日時などを表示できる(写真01)。
kernelCommandLineの指定を確認するには、Linuxでdmesgを利用する(写真02)。これは、カーネルの出力するメッセージを表示するもの。具体的には、
dmesg | head
とすると、2行目に“Command line:”という行があり、指定されたコマンドライン(デフォルト値を含む)が表示されている。
Windows 11では、Linux起動時などのメッセージを表示するデバッグコンソールを別コンソール端末に表示することができる。「debugConsole=true」とすることで、デバッグコンソール表示が有効になる(写真03)。このとき、自動的にカーネルのコマンドラインに“debug”が指定されることに注意が必要だ。
メモリ関連の設定項目
WSL2のメモリ関連設定項目には、“memory”、“swap”、“swapFile”、“pageReporting”、“idleThreshold”の5つがある(表03)。
WSL2が利用するメモリは、memory設定項目で指定するが、これは、最大割り当てメモリ量を指定するもの。WSL2を動作させる軽量ユーティリティ仮想マシンに対して、Hyper-Vなどの仮想マシンと同じく動的メモリ割り当てが行われている。このため、実際に利用するメモリのみが割り当てられる。デフォルトでは、Windows 10の場合、ホストマシンの物理メモリの最大80%、Windows 11では、物理メモリの50%または8ギガバイトのうちの小さい方がとなる。しかし、これよりも割り当てを小さくしたい場合、あるいは、より多くメモリを割り当てたい場合にmemory設定項目を使い、絶対値で最大割り当てメモリ量を指定する。このとき、割り当てサイズは“GB”(ギガバイト)、“MB”(メガバイト)といった単位を指定できる。たとえば、16ギガバイト割り当ては「memory=16GB」となる。
“swap”、“swapFile”は、Linuxのスワップの制御を行うもの。標準では、ホストの物理メモリの25%がスワップサイズとして指定される。ただし数値はギガバイト単位に「切り上げ」なので、どのような場合にも最低で1ギガバイトのスワップが指定されることになる。これも前述のfreeで確認可能だ。指定は、
swap=8GB
swapfile=swapfile=C:\\temp\\linuxswap.vhdx
のように行う。vhdxファイルが存在しない場合、自動的に作成される。このswapFileの指定でもパス区切り文字を“\\”とする点に注意。
WSL2側でメモリ割当量やスワップのサイズを調べるにはfreeを使う(写真04)。このときオプション“-h”を使うとよい。
“pageReporting”、“idleThreshold”は、軽量ユーティリティ仮想マシンがLinux側から不要メモリを回収する場合の挙動を変更するもの。pageReportingは、Linux側からの空きメモリページ通知機能をオンオフする。デフォルトではtrueで空きメモリページ通知は有効になっている。空きメモリ通知を禁止すると、不要メモリの回収も行われなくなる。この状態でWSL2が確保したメモリは、軽量ユーティリティ仮想マシンが終了あるいはシャットダウン(wsl.exe --shutdown)が実行されるまで確保されたままになる。
不要メモリの回収は、WSL2内でプロセスがメモリを解放することと並行して行われる。ただし、この状態だとメモリの解放されたところと利用中の領域が混在してしまうことがある。このため、WSL2はメモリコンパクションを利用する。メモリコンパクションは、Linuxの機能で、空きメモリを連続させて大きな領域とするもの。WSL2では、このメモリコンパクションを使い、不要となったメモリ領域を連続するように配置させる。このコンパクションの起動条件を設定するのがidleThreshold(アイドル閾値)だ。デフォルト値は1となっている。ゼロにするとWSL2はメモリコンパクションを発生させない。
メモリコンパクションの発生は、dmesgで見ることができる。具体的には以下のコマンドラインを使う。
dmesg --time-format iso | grep 'memory compaction'
Ubuntuでstress(要インストール)を使いメモリを利用したあと開放し、その後5分間のアイドル状態でメモリコンパクションが発生するかどうかを調べた。idleThresholdの数字を大きくするとメモリコンパクションが発生しない場合が増えた。このため、デフォルト値の1が最小値と考えられ、この値を増やすことで、コンパクションの頻度を下げることができるようだ。
プロセッサ関連の設定項目
プロセッサの設定項目には、“processors”、“nestedVirtualization”の2つがある(表04)。“processors”は、Windowsでいう「論理プロセッサ」数を指定するもの。Linuxではこれをprocessorと呼ぶ。processor数を調べるには、procファイルシステム“/proc/cpuinfo”を使うのが基本だが、lscpuでもよい(写真05)。
nestedVirtualizationは、Linuxで仮想マシン支援機能を使うかどうかを指定する(Windows 11のみ)。そのためにはCPUに「Nested VM」機能が必要で、インテルCPUならば第5世代Core(Broadwell)以降、AMDならばZen世代以降のCPUが対応する。WSL2が仮想マシン支援機能の有無を認識しているかどうかは、前述の/proc/cpuinfoやlscpuで"vmx"(インテルの仮想マシン支援機能)、"svm"(同AMD)といった文字列を探す(写真06)。
その他の設定項目
その他の項目には、(表05)のようなものがある。“localhostForwarding”は、WSL2側でのTCPポートをホストマシンのlcoalhostで待ち受け可能にするもの。WSL2は仮想マシンなのでWin32側とはIPアドレスが異なっている(WSL1では一致していた)。WSL2側のポート3000でHTTPサーバーを動作させたときWin32側からは「http://localhost:3000/」で接続できるようになる。
“guiApplications”は、Windows 11のWSLが持つLinux GUIアプリケーション実行機能のオンオフを設定するもの。この機能がオンになっていると専用のSystemディストリビューション用の仮想マシンが動作するためメモリ利用量が増える。
vmIdleTimeoutは、WSLディストリビューションのセッションが終了したあと、軽量ユーティリティ仮想マシン全体を終了させるまでの待ち時間を指定する。この値を小さくするとすぐに仮想マシンが終了するが、パイプラインでWin32コマンドとWSLコマンドを交互に実行するような場合、この値が小さすぎると仮想マシンが再起動するのに時間がかかってしまう。
WSL2の設定を使うことで、ホストマシンのリソース消費を抑える、あるいはリソース割り当てを増やすことでWLS2側の性能を向上させることが可能になる。前者は、ハードウェアスペックの高くないマシンの場合に有効で、後者は、WSLで高い性能を要求するアプリケーションの利用に有効だ。