Here I'll store my notes on WSL tuning. I mainly use WSL to do Dev Containers, so I need it to run as smooth as possible. My main problems include: memory and disk size. Let's see what we can do to address the problem.
How big are my virtual hard disks?
The following script will show the name of the distro, the size and the path of the virtual hard disks:
Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\ | ForEach-Object {
$psPath = (Get-ItemProperty -Path $_.PsPath)
$distro = $psPath.DistributionName
$vhdxPath = $psPath.BasePath + "\ext4.vhdx"
$vhdxSize = (Get-Item $vhdxPath).Length / 1GB
[PSCustomObject]@{
DistributionName = $distro
SizeGB = [math]::Round($vhdxSize, 2).ToString("0.00")
VHDXPath = $vhdxPath.Replace("\\?\", "")
}
} | Format-Table -Wrap -Property `
DistributionName, `
@{Name='SizeGB'; Expression={$_.SizeGB}; Alignment='right'}, `
VHDXPath
Now you know what might eat up your hard disk.
Manually shrinking the hard disks
The following script will prune your docker containers and image, iterate your virtual hard disks and perform a shrink:
# make sure we're admin
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
Write-Host
Write-Host "Pruning containers" -ForegroundColor Blue
docker container prune --force
Write-Host
Write-Host "Pruning images" -ForegroundColor Blue
docker image prune --all --force
wsl --shutdown
Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\ | ForEach-Object {
$psPath = (Get-ItemProperty -Path $_.PsPath)
$distro = $psPath.DistributionName
$vhdxPath = $psPath.BasePath.Replace("\\?\", "") + "\ext4.vhdx"
$vhdxSize = [Math]::Round((Get-Item $vhdxPath).Length / 1GB, 2).ToString("0.00")
Write-Host
Write-Host "Shrinking distro: " -NoNewline -ForegroundColor Blue
Write-Host $distro -ForegroundColor Yellow
Write-Host " - before: $vhdxSize"
try {
Optimize-VHD -Path $vhdxPath -Mode Full -ErrorAction Stop
$vhdxSize = [Math]::Round((Get-Item $vhdxPath).Length / 1GB, 2).ToString("0.00")
Write-Host " - after: $vhdxSize" -ForegroundColor Green
} catch {
if ($_.Exception.Message -match "Virtual hard disk files must be uncompressed and unencrypted and must not be sparse.") {
Write-Host " - cannot shrink disk as it is already sparse" -ForegroundColor Red
} else {
Write-Error "Error: $($_.Exception.Message)"
exit
}
}
}
Write-Host
Read-Host -Prompt "Press Enter to exit"
But you might want to go one further and make those disks sparse!
Stop the bleeding
We can stop the bleeding by configuring WSL2 differently. The September 2023 update includes some great new features:
- Automatic memory reclaim.
- Sparse virtual hard disks, which will give the disk space back.
- Better networking.
Upgrade to the latest release
First you'll need to upgrade to the store version, then to the pre-release version:
wsl --shutdown
wsl --update
wsl --update --pre-release
WSL Config
Next, you might want to now how many (logical) processors and memory you have:
$logicalProcessors = (Get-WmiObject -Class Win32_ComputerSystem).NumberOfLogicalProcessors
$totalMemoryGB = [Math]::Round((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
$output = "Number of Logical Processors: $logicalProcessors"
$output += "`nTotal Memory (GB): $totalMemoryGB"
Write-Output "$output"
Based on these settings you might want to tune your WSL config. I open it by doing code (Join-Path (Resolve-Path ~) .wslconfig)
in a terminal and adding the following to the file:
[wsl2]
memory=10GB
processors=14
guiApplications=false
[experimental]
autoMemoryReclaim=gradual
sparseVhd=true
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
I configured my memory to be ~2/3 of my machine. I keep 2 cores back for the processor config.
Notice how I disabled Linux GUI applications, as it keeps messing up my dev containers with the error: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: \wsl.localhost\Ubuntu\mnt\wslg\runtime-dir\wayland-0. Adding guiApplications=false
will fix that.
Settings all your WSL distros to sparse
Now that we've updated and activated our sparse disk, we can apply them to all disks:
wsl --shutdown
Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\ | ForEach-Object {
$distro = (Get-ItemProperty -Path $_.PsPath).DistributionName
Write-Host
Write-Host "Changing distro: " -NoNewline -ForegroundColor Blue
Write-Host $distro -ForegroundColor Yellow
wsl --manage $distro --set-sparse true
}
Changelog
- 2024-04-03: Make sure we disable Wayland / Linux GUI apps to prevent errors on our Dev Containers.
- 2024-02-20: Fixed the opening of the
~/.wslconfig
if it does not exist.