Open dsmaher opened 4 years ago
Absolutely agreeing with jerivas, we have came to a point that "just buy an ssd".
you shouldn't use Docker with WSL at this stage, just go with another route. Docker Desktop is way too slow and way too bloated, and CLI Docker without Docker Desktop is eating your space until there is nothing left.
@canercetin-randomguy The best way to work with docker is to completely bypass docker desktop. My VHDL image for docker containers is about 1500 MB. The /var/lib/docker
folder (especially the huge /var/lib/docker/overlay2
folder) is in a qcow2 image in a folder outside the vhdx, in /mnt/c/whatever_you_like
. This way, container activity doesn't add any garbage to vhdx files. qcow2 format is way better at managing an ext4 filesystem inside.
Other than that, it is a good practice to prune your unused containers and keep some kind of hygiene in the docker folder.
@jerivas I understand your frustration, but if they lock this thread, it would be like accepting that the solution is to get a bigger drive. That is the current first-place solution in the Docker Desktop documentation:
So, just because we have come to a point that "just buy an SSD" seems the only way forward, is the reason why this thread shouldn't be locked.
The real problem here is not in WSL, it is actually the inability of Hyper-V to properly manage space in non-NTFS partitions inside VHDX images. WSL team had no other choice but to use VHDX (from Microsoft) to virtualize the storage hardware, so probably this issue should be elevated to another team able to evolve the VHDX management system....
...KNOCK, KNOCK... MICROSOFT, ARE YOU THERE??????
Can someone at Microsoft please lock this issue until an official response is ready to be shared? The conversation has been completely derailed π
https://github.com/microsoft/WSL/issues/4699#issuecomment-1433530372
The problem is that a locked issue can't even receive π, which may end up making this issue and comments seem to be less important / with less interest than it actually is (although it already has more than 680 π, so this issue is already considered very important by the community).
In any case, it's possible to customize the subscription (right above the button) to make it notify only when this issue is closed, to avoid undesired comments.
This is really hurting me on running scientific workload in docker I've been running batch jobs on my machine and only remove containers on a scheduled command and still my system is running out of space... bringing me to this issue https://github.com/docker/for-win/issues/244 which is linked to this issue as a base problem.
This is really hurting me on running scientific workload in docker I've been running batch jobs on my machine and only remove containers on a scheduled command and still my system is running out of space... bringing me to this issue docker/for-win#244 which is linked to this issue as a base problem.
@DanielHabenicht I am using docker for development, with a lot of scripts creating and pruning containers and images. I use wslcompact after I finish each work and delete all the garbage in the docker image. That ensures my WSL docker image is always small.
I have improved my WSL docker image. It is now a 311 MB VHDX, 7zipped down to 48MB. I use these 3 supporting functions in powershell $PROFILE to use docker from PowerShell:
function docker { wsl -d alpine-docker docker $args }
I also have this other function in my PowerShell profile to prune everything leaving the image clean.
function dockerclean {
docker stop $(docker ps -a -q) -t 0
docker container ls -a
docker image ls -a
docker system prune -a
}
And this one to know the actual size used by docker images and containers
function dockersize { wsl -d docker du -hd 1 /var/lib/docker/ }
Then, when I work with containers, I do:
start WSL docker image from PowerShell (note >
prompt for PowerShell commands, and $
for shell commands):
> wsl -d alpine-docker
$ dockerd &
$ exit
All my docker work here.....
Then after working:
> dockerclean
> wslcompact -c -y alpine-docker
That returns my alpine-docker VHDX from tens of GBs back to 311 MB. Always.
Windows should atleast collaborate with @okibcn and recommend a solutionπ€ WSL2 was one of the reasons for not switching back to Mac OS, but issues like these make WSL2 less attractive.
For anyone who's using WSL2 and need to make their disk larger than the old 250G size. I cleaned up my drive and used: https://github.com/microsoft/WSL/issues/4699#issuecomment-627133168 to get back the space.
After restoring to my minimum size, I used these docs to make the maximum disk larger: https://learn.microsoft.com/en-us/windows/wsl/disk-space
For anyone who's using WSL2 and need to make their disk larger than the old 250G size. I cleaned up my drive and used: #4699 (comment) to get back the space.
After restoring to my minimum size, I used these docs to make the maximum disk larger: https://learn.microsoft.com/en-us/windows/wsl/disk-space
wslcompact also updates the drive capacity to 1 TB while reducing the size of the VHDX file in three easy steps:
wslcompact -c -y DISTRO
wsl --shutdown
wsl -d DISTRO resize2fs /dev/sdc
You will have a compacted VHDX file with a whole 1TB in your ext4 filesystem.
I couldn't get the optimize-vhd
command to work, but using the Hyper-V Manager GUI had no problems.
may be there is way to complete stop using this vhdx images for docker images ? any way to mount just directory ? I found that manage disk space with this really disturbing.
Will just add its 2023, and still no integrated way to receive all my space back. I just ran df -h
after running compact vhd I get this
Filesystem Size Used Avail Use% Mounted on`
/dev/sdc 1007G 211G 745G 23% /`
Why do you not make a tool which prevents making the whole experience an adrenaline rush for if my data will be corrupt afterwards... Feel like we're all asking for something that's very reasonable to achieve in the last 4 YEARS.
I tried to use Resize-VHD to reduce the maximum size of a freshly installed distro from the default 1TB, but I just get the following error:
> Resize-VHD -path ext4.vhdx -SizeBytes 128GB [β¦]AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx': The requested operation could not be completed because the virtual disk's minimum safe size could not be determined. This may be due to a missing or corrupt partition table. (0xC03A0026).
Anyone got an idea what might be going wrong there?
Or is there another way to reduce the maximum size?
Wslcompact looks like a great tool for shrinking an image that has already got out of hand, but I'd like to reduce the 1TB default limit on the VHDX size while the image is still small, to prevent it from eating up too much of a 512GB SSD.
There's a lot of comments on this issue already but if it hasn't been mentioned yet, I partitioned my disk and made a 256GB partition exclusively for WSL, and so far haven't had any issues with that.
There is like, 120Gb of usave in VHDX, and when I compact it goes to 40Gb...
My entire SSD as 256Gb in total, so wsl is eating half of that for no good reason :(
There's a lot of comments on this issue already but if it hasn't been mentioned yet, I partitioned my disk and made a 256GB partition exclusively for WSL, and so far haven't had any issues with that.
Interesting. I didn't know you could install WSL to a dedicated partition. Is there an official guide on that?
@Chiramisu
Interesting. I didn't know you could install WSL to a dedicated partition. Is there an official guide on that?
As far as I know, this is not possible, i.e. the WSL itself cannot be installed on a separate partition.
But for WSL2 distros you can move disk image files to a custom folder using --export
/--import
. See https://github.com/docker/for-win/issues/13408#issuecomment-1523397767 for detailed example (replace docker-desktop-data
with your distro).
If you're using Docker Desktop you can also try a different approach. See another https://github.com/docker/for-win/issues/13408#issuecomment-1642506519.
Nor wsl-compact
nor optmize-vhd
works properly. optimize-vhd
not cleaning the extra space at all, wsl-compact
clean the space a bit, once (still my instance is near 50gb with one dumb project installed and nothing else).
Hi folks, we have just put out a new experimental feature in WSL that aims to address this in the latest update. You can now run wsl --manage <distroName> --set-sparse true
to set it to a sparse VHD that will automatically reclaim memory. This will allow it to shrink in size as you use it!
More info on this release and the changes can be found here in the blog post. Please tell us what you think!
You can now run
wsl --manage <distroName> --set-sparse true
to set it to a sparse VHD that will automatically reclaim memory. This will allow it to shrink in size as you use it!
Makes sense that this is experimental at first, but if no issues arise, will sparse VHDs become the default in a future WSL update?
@craigloewen-msft Nice! Do we need to worry about or think about SSD wear and tear when sparse is enabled?
Hi folks, we have just put out a new experimental feature in WSL that aims to address this in the latest update. You can now run
wsl --manage <distroName> --set-sparse true
to set it to a sparse VHD that will automatically reclaim memory. This will allow it to shrink in size as you use it!More info on this release and the changes can be found here in the blog post. Please tell us what you think!
Awesome! Does this work with WSL 2 instance whose VHD images have had NTGS compression applied to them on the Windows side, too?
@craigloewen-msft Nice!
I ran wsl --manage ubuntu --set-sparse true
and purged docker data as you showed in the demo video. Docker Desktop's ext4.vhdx
did not shrink.
Since I have an existing docker-desktop-data
distro, as managed by docker desktop, would I also need to wsl --manage docker-desktop-data --set-sparse true
? Makes sense I would need that, but I did not see any explicit instructions for this case and since this is experimental I don't just want to yolo it.
Yes to clarify you would need to run it for your given distro. So @daniel5gh please run wsl --manage docker-desktop-data --set-sparse true
and you should see it now shrink in size automatically. (Doing it for Ubuntu only affects your Ubuntu distro :) )
Yes to clarify you would need to run it for your given distro. So @daniel5gh please run
wsl --manage docker-desktop-data --set-sparse true
and you should see it now shrink in size automatically. (Doing it for Ubuntu only affects your Ubuntu distro :) )
Awesome, thanks for the clarification! But, it doesn't seem to work in my case.
I first enabled sparse on docker-desktop-data
which appeared to not do anything with the vhdx's size, at least not after about 5 minutes and building some dev images and pruning them again. I then shutdown wsl and enabled sparse on docker-desktop
as well. Again rebuilding images and pruning did not change the vhdx's filesize. (I did this thinking that generating some activity on the filesystem could kick in the vhd optimizing).
For good measure I shutdown and restarted wsl once more.
Should I expect the vhdx to be smaller after these actions?
The file I am looking at is "C:\Users\x\AppData\Local\Docker\wsl\data\ext4.vhdx"
and its size is the same (123 GB) as before I updated WSL today.
The first prune, before enabling sparse on docker-desktop-data
, said Total reclaimed space: 64.22GB
.
@daniel5gh I haven't tested this myself, but I guess you should also prune the docker build cache.
See https://docs.docker.com/engine/reference/commandline/builder_prune/
You can also try the Disk Usage extension to do the same in the Docker Desktop GUI: https://hub.docker.com/extensions/docker/disk-usage-extension
@mmarinchenko Thank you for your suggestion, but I think docker prune --all
should also reclaim the build cache, judging from its output:
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
I will give the Disk Usage extension a go, haven't used that before. thanks. The output from this extension is in line with my expectations:
2.23 GB images, the ones I just built. 27.25 GB volumes, 2.89 MB build cache.
@daniel5gh You're right, I just didn't realize you were using system prune from your comment aboveπ
If docker system df
shows the same thing (0% reclaimable space), then I join your question) Thanks for testing!
docker-desktop-data --set-sparse true
specific troubleshootingext4.vhdx
...--export
+ --import
workaround?, diskpart
, or wslcompact
)TL;DR:
docker-desktop-data
as shown below and still have a fair amount of excess data remaining from some unknown source.du
command (or windows explorer "properties" view), you can see that the WSL2 sparse feature is working, but otherwise appears to not be reducing in disk-size, space is still reclaimed.docker-desktop-data
, purging all WSL2 data via the GUI will clear the unknown filler. You may want to explore other suggestions prior to keep your actual data, let us know if it removes the mystery VHDX disk usage π
After the purge, the data disk .vhdx
was now 1.4GB, which seems to match the /mnt/wsl/docker-desktop-data
below. Nothing else changed related to the other docker locations.
Yes to clarify you would need to run it for your given distro. please run
wsl --manage docker-desktop-data --set-sparse true
and you should see it now shrink in size automatically.
wsl.exe --shutdown
.# Curious if this would return disk-space that had since been freed:
$ wsl.exe --manage docker-desktop-data --set-sparse true
Conversion in progress, this may take a few minutes.
The operation completed successfully.
# Confirm filepath:
$ (Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq 'docker-desktop-data' }).GetValue("BasePath") + "\ext4.vhdx"
\\?\C:\Users\polarathene\AppData\Local\Docker\wsl\data\ext4.vhdx
# Checking disk size after making the file sparse:
$ ls -lh /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
-rwxrwxrwx 1 polarathene polarathene 35G Sep 24 19:55 /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
$ du -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
27G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
$ du --si /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
29G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
$ du --bytes -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
35G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
$ du --bytes --si /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
37G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# From du --help:
--apparent-size
print apparent sizes, rather than disk usage; although the apparent size is usually smaller,
it may be larger due to holes in ('sparse') files, internal fragmentation, indirect blocks, and the like
-b, --bytes
equivalent to '--apparent-size --block-size=1'
-h, --human-readable
print sizes in human readable format (e.g., 1K 234M 2G)
--si
like -h, but use powers of 1000 not 1024
From Windows Explorer, right-click => properties:
34.3 GB (36,909,875,200 bytes)
26.2 GB (28,210,036,736 bytes)
NOTE: Above information was collected after the first attempt with sparse not freeing any space (C:\
was at 3GB disk space left remaining).
wsl --shutdown
, etc) but no improvement.docker system prune
(withouot -a
) prior to upgrading to WSL2 2.0.0, but I still had a few GB of images I could clear.docker system prune -a
as another attempt to free storage, it output 1.6GB had been reclaimed. C:\
reported 11GB disk was now free (which is a fair bit more than 1.6GB π€ )..vhdx
file had not changed in reported disk size, but as observed from Windows and WSL, the sparse size on disk is roughly the amount I gained in C:\
... so it appears to be working?Despite that, it's unclear what else is using 26GB for a volume that's supposedly only data for Docker?
# Absolutely cleared all user data:
$ docker builder du
Reclaimable: 0B
Total: 0B
$ docker builder prune -a
WARNING! This will remove all build cache. Are you sure you want to continue? [y/N] y
Total: 0B
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 0 0 0B 0B
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B
$ docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
$ docker volume ls
DRIVER VOLUME NAME
$ docker volume prune -a
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
# Presumably some of this is used
$ du -sh /usr/local/lib/docker/
40K /usr/local/lib/docker/
$ du -h --max-depth=2 /Docker
221M /Docker/host/bin
248M /Docker/host/cli-plugins
674M /Docker/host/wsl
2.5G /Docker/host
2.5G /Docker
$ du -h /mnt/wsl/docker-desktop-data
0 /mnt/wsl/docker-desktop-data/data
443M /mnt/wsl/docker-desktop-data/isocache/entries/docker-wsl-cli.iso
171M /mnt/wsl/docker-desktop-data/isocache/entries/docker-for-wsl.iso
747M /mnt/wsl/docker-desktop-data/isocache/entries/services.iso
1.4G /mnt/wsl/docker-desktop-data/isocache/entries
1.4G /mnt/wsl/docker-desktop-data/isocache
1.4G /mnt/wsl/docker-desktop-data
$ df -h | grep -i docker
/dev/sde 1007G 1.4G 955G 1% /mnt/wsl/docker-desktop-data/isocache
none 7.7G 12K 7.7G 1% /mnt/wsl/docker-desktop/shared-sockets/host-services
/dev/sdd 1007G 61M 956G 1% /mnt/wsl/docker-desktop/docker-desktop-user-distro
/dev/loop0 443M 443M 0 100% /mnt/wsl/docker-desktop/cli-tools
drvfs 450G 439G 12G 98% /Docker/host
You can also try the Disk Usage extension to do the same in the Docker Desktop GUI: https://hub.docker.com/extensions/docker/disk-usage-extension
Nothing in use as expected from above:
Perhaps there are some other options to explore here (not too keen to read through 180+ hidden messages though).
It doesn't look like docker-desktop-data
VHDX is actually using 26GB, I don't have the disk space free to explore some of those and since I've already thrown all my actual docker data away, I might as well go with the GUI purge option π€·ββοΈ
Success!
$ du --bytes --si /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
1.6G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
C:\
reclaimed π Obviously not ideal to purge the entire docker-desktop-data
. Next time I'll try another workaround for compacting the vhdx.
NOTE: I had also discovered C:\Users\polarathene\AppData\Local\Temp\docker-scout\sha256
using 11GB from having "Experimental Features" enabled, but never having interacted with the Docker Scout tab/feature. I probably did enable experimental features; I had removed this 11GB prior to the GUI purge, but noticed nothing reclaimed from the VHDX (as expected).
@polarathene wow thanks for this. I was getting nuts trying sparseVhd=true
and seeing the vhdx file size was always the same in Windows Explorer even after deleting GBs of data but now I see it's displayed in "size on disk" and eventually in This Pc.
@polarathene
- I was a bit surprised to find this prevented accessing my existing VMs (unless I lose their suspend state and disable the virtualization CPU
VT-x
/AMD-V
feature). Alternatively I have to disable WSL2 (with that apparently involving a registry edit and reboot, or similar inconvenient ways to switch).
Yes, that's because Hyper-V (and therefore WSL2) is actually a native hypervisor. This means that when you enable Hyper-V/WSL2, your Windows "host" actually becomes a privileged guest relative to the virtualization layer. And after that, other installed virtualization solutions (such as VMware for Windows, which is a hosted hypervisor) lose access to hardware virtualization support, since this now requires that Hyper-V nested virtualization be enabled and supported by these solutions (VMware Player, in your case).
My guess is that docker system prune -af
just drops the ext4 inodes (as expected). And for the sparse VHD feature, this is not enough, because the actual VHD space is not zeroed.
Just adding this in case it is useful for anyone.
And for the sparse VHD feature, this is not enough, because the actual VHD space is not zeroed.
The other day I also tried filling unused space in the ext4 fs with zeroes, basically as a wild guess. It did not have an effect on the vhdx filesize
# (wsl -d docker-desktop)
# based on disk size and used size I assumed this is the right filesystem
cat /dev/zero > /tmp/docker-desktop-root/mnt/host/wsl/docker-desktop-data/version-pack-data/community/docker/overlay2/zero
# until output cat: write error: No space left on device
rm /tmp/docker-desktop-root/mnt/host/wsl/docker-desktop-data/version-pack-data/community/docker/overlay2/zero
I don't know what is needed for the vhdx sparse feature, but the above did not seem to do that.
And for the sparse VHD feature, this is not enough, because the actual VHD space is not zeroed.
Correct implementation of this functionality should use the trim command of the disk interfaces which has been supported in Linux for many years already. There are multiple articles about this on the internet, for example: How to Enable TRIM For SSD in Ubuntu
Unfortunately the WSL release blog says absolutely nothing about how the OS should indicate which disk blocks should be freed: Automatic disk space clean up (Set sparse VHD)
Hi folks, we have just put out a new experimental feature in WSL that aims to address this in the latest update. You can now run
wsl --manage <distroName> --set-sparse true
to set it to a sparse VHD that will automatically reclaim memory. This will allow it to shrink in size as you use it!More info on this release and the changes can be found here in the blog post. Please tell us what you think!
Awesome! Does this work with WSL 2 instance whose VHD images have had NTGS compression applied to them on the Windows side, too?
I tried it after I finally managed to get the 2.0.0 pre-release package to show up and install, and everything works like a charm!
(Edit: See my comment below.)
Correct implementation of this functionality should use the trim command of the disk interfaces which has been supported in Linux for many years already. There are multiple articles about this on the internet, for example: How to Enable TRIM For SSD in Ubuntu
Unfortunately the WSL release blog says absolutely nothing about how the OS should indicate which disk blocks should be freed: Automatic disk space clean up (Set sparse VHD)
There's an 'fstrim
' command in util-linux that you can use to trigger this manually in the meantime.
I could really use some help with this. I noticed today my Docker was acting weird and restarting. I couldn't get it properly working and directly noticed my whole 512GB SSD was filled. With further investigation it seemed that my C:\Users\%user%\AppData\Local\Docker\wsl\data\ext4.vhdx has grown to almost 350GB. I've tried everything, clean Docker stuff, but that's only 15GB in total, and use the diskpart or optimize-vhd command. Both don't seem to do anything. Looking at my Ubuntu distro, it's using around 35GB.
I then tried the sparse option introduced in the new WSL, hoping that that would fix it. But also nothing, still the same size. Sadly I can't really do anything else since I have only 4-5GB left on my SSD. I hope I don't have to start from scratch!
@Gerben321, as @RandomDSdevel mentioned above you, if you change to sparse after not having been sparse, you'd need to run sudo fstrim -v /
. Setting it to sparse only means that going forward empty space is reclaimed as it is produced. It doesn't have an effect on what happened in the past unless you use something fstrim to clean up after the fact.
So long as you see the discard option under findmnt -l /
you should be seeing space reclaimed on the host when it is freed on the guest (inside wsl).
[[Failed]]
I'm not seeing the size of the .vhdx
file change using fstrim -v /
although I know everything is setup correctly. Using Win10.
I'm going to set sparse back to false and run DiskPart to compact the disk and see if I can reclaim the size back down, then turn sparse back on and see if it works. I don't mind doing this if I need to, just don't want to deal with a 500G .vhdx
file.
Results:
Unfortunately the above corrupted the instance and no longer allowed for connection from WSL using the pre-release
[[Worked]]
I restored my non-sparse backup of the above large .vhdx
distro. Launched WSL and cleaned up everything I didn't need (approx. 150G) which included a ton of Rust compiled debug code targets as well as using docker prune -a
.
wslcompact
instead to free up the space on the .vhdx
partition.wsl --manage <distro> --set-sparse true
and successfully am able to start wslNote: I had already upgraded the pre-release, so not sure if that is why DiskPart kept messing up the distro when using the compact command.
There are two different sizes. Setting sparse will only reduce the "Size on disk"
@pmartincic I understand this. Both those numbers are the same in my case.
Are we saying once the Size on disk increases, it never recovers space even if we use sparse=true
? I was saying above that it never recovered space once I removed files with sparse turned on.
Are we saying once the Size on disk increases, it never recovers space even if we use
sparse=true
? I was saying above that it never recovered space once I removed files with sparse turned on.
My earlier comment explains what to expect.
properties
window) for ext4.vhdx
, even after you set sparse.ext4.vhdx
then choose properties
), but not the "Size".du --bytes --si
/ du --bytes -h
commands--apparent-size
, for on disk-size omit the --bytes
option) pointed at the ext4.vhdx
file (if you don't know the path, use the PowerShell command provided in my comment link).wslcompact
require free space to create a new .vhdx
that is compacted, and only after that is created does it delete the original to replace it.fstrim
advice to work with Docker Desktop, since you're not using the virtual disk directly (as /
aka root_), you will need to run that command to target the docker-desktop-data
mount-point instead (not /
).
fstrim --all
without specifying a mount-point.--verbose
it will also list the filesystems it applies the command to and how many bytes were discarded (if any).Out of curiosity does sparse mode only clear the equivalent deleted data size after enabling or does it go through the whole disk?
Let me rephrase that... If I have a WSL disk I've been using for a year (so there's definitely some unreleased empty space), write a 100MB file, enable spare mode and delete that 100MB file, can I reasonably expect the "size on disk" to shrink more than the 100MB difference since enabling it?
@darkvertex Look a few comments above yours, less than 24 hours ago: https://github.com/microsoft/WSL/issues/4699#issuecomment-1735824244
You'll want to use fstrim
.
Can please anyone confirm that the new functionality "Automatic disk space clean up (Set sparse VHD)" is based on the HDD trim command? Then we would know if it makes sense to use the fstrim
command in Linux. It is a pity that we do not get this information from Microsoft. :(
https://github.com/microsoft/WSL/issues/4699#issuecomment-1735824244 is from a collaborator so I guess it's trustable?
I found https://learn.microsoft.com/en-us/windows-server/administration/performance-tuning/role/hyper-v-server/storage-io-performance#unmap-notification-integration which suggests sparse (a.k.a expandable or dynamic) vhdx uses SCSI unmap command to signal deleted files. From Google results fstrim
can also issue unmap commands in addition to the trim commands.
My earlier comment explains what to expect.
None of this applies to my situation. I have the sparse settings turned on and added 3G of files to a directory, then deleted them and the instance did NOT reclaim the Size on disk
or change any sizes given when doing a du -sh
on the mounts. Also fstrim
had no affect also.
@talves do you have a reproduction? Are you mounting your own .vhdx
or is it created and mounted for you by software like Docker Desktop?
For Docker Desktop I used docker pull
on some images to increase the disk size (and identify the mount point affected via df -h
from that increase):
# Windows properties: "Size"
$ du --bytes -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
14G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# Windows properties: "Size on disk" (potentially smaller):
$ du -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
13G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# Partition, disk usage and mount-point:
$ df -h
/dev/sde 1007G 4.9G 951G 1% /mnt/wsl/docker-desktop-data/isocache
# Remove all the images pulled:
$ docker system prune -a
Total reclaimed space: 3.479GB
# No change:
$ du --bytes -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
14G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# Reflects the change from deletion (C:\ free space increased by similar amount):
$ du -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
9.8G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
$ df -h
/dev/sde 1007G 1.4G 955G 1% /mnt/wsl/docker-desktop-data/isocache
# No benefit since data was freed from deletion:
$ sudo fstrim --all --verbose
/mnt/wsl/docker-desktop-data/isocache: 0 B (0 bytes) trimmed on /dev/sde
/: 0 B (0 bytes) trimmed on /dev/sdc
I made the Docker/wsl/data/ext4.vhdx
file sparse when it was reporting 12G with --bytes
, not realizing that was the wrong value to look at and should have been omitted π
So it may have been 9.8G (not sure if Docker Desktop GUI purge setting removed the prior sparse setting)
The remaining space isn't going to free itself though, but you can see that it is possible to track the change. Not sure why that wouldn't work for you. If you have a reproduction without Docker that'd be helpful π
df -h
vs du -sh
Observation with the /mnt/wsl/docker-desktop-data/isocache
mount point.
While df -h
reflects actual disk usage, if you use du -h
on that mount point it seems you'll always get the base 1.4G
size? (for the docker-desktop-data
disk):
# Actual allocated (sparse) size on disk:
$ du -h /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
13G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# Will grow as needed regardless as a dynamic sized vhdx (1TB max):
$ du -h --bytes /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
17G /mnt/c/Users/polarathene/AppData/Local/Docker/wsl/data/ext4.vhdx
# Actual size of filesystem recognized:
# This is 1.4G originally, which matches the on-disk size when Docker Desktop purges (recreates) the disk:
# While allocated size above with sparse enabled
$ df -h /mnt/wsl/docker-desktop-data/isocache
Filesystem Size Used Avail Use% Mounted on
/dev/sde 1007G 4.7G 952G 1% /mnt/wsl/docker-desktop-data/isocache
# Does not reflect "Used" from `df -h`:
# (_NOTE: Despite the `.iso`, these are actually directories_)
$ du -h /mnt/wsl/docker-desktop-data/isocache/entries
443M /mnt/wsl/docker-desktop-data/isocache/entries/docker-wsl-cli.iso
171M /mnt/wsl/docker-desktop-data/isocache/entries/docker-for-wsl.iso
747M /mnt/wsl/docker-desktop-data/isocache/entries/services.iso
1.4G /mnt/wsl/docker-desktop-data/isocache/entries
TL;DR: 3GB was written to docker-desktop-data
disk, but 5GB in the file buffer cache (free -m
) seemed to use disk space, not just memory? This was freed after quitting both Docker Desktop and the WSL2 terminal that ran the docker build
command (wsl --shutdown
speed up the process of reclaiming diskspace).
I have C:\
with 30GB of disk space free currently:
golang:1.21
. So about 3GB, although the golang
base image isn't stored in the build cache or reported by docker system df
.docker system df
reports 2.6GB of build cache can be reclaimed, while df -h
indicates a 3.5G increase for docker-desktop-data
(/dev/sde
), however C:\
dropped down to 22GB free.docker system prune -a
reports reclaiming 2.6GB storage and df -h /dev/sde
shows it has dropped back down to 1.4G. C:\
is now at 25GB free.VmmemWSL
process (which was using 5GB) closed itself.
free -h
, I can see the filesystem buffer/cache has 5.5G allocated, and without enabling the experimental feature (which IIRC isn't compatible with Docker Desktop until cgroupsv2 can be used), this memory won't be freed implicitly.echo 3 | sudo tee /proc/sys/vm/drop_caches
releases that buffer, and VmmemWSL
does drop accordingly, but the free space doesn't get reclaimed immediately. Closing Docker Desktop seemed required, after which the disk space slowly was reclaimed each minute. Closing the WSL2 terminal was also required to release a few more GB. Once VmmemWSL
process is gone it seems to correlate with the affected disk space being free.wsl.exe --shutdown
from PowerShell instead. The 5GB disk usage related to this (not a .vhdx
?) would also be restored.wslcompact
pipes an export into an importI also noticed that wslcompact
is a convenience wrapper for wsl --export
+ wsl --import
, and trying that failed for me, not because of disk-space, but because I lacked enough RAM. After the failure, PowerShell continued to hold 8GB of memory until I closed that terminal tab. The .vhdx
to convert had 8.3GB "size on disk" (but otherwise seen as 16.8GB "size")
The following attempt also used 5GB of disk during that import
+ export
operation (disk reclaimed after the failure automatically, memory didn't):
# Shutdown first to avoid causing any accidental corruption during the operation:
$ wsl --shutdown
# Export to stdout, pipe into import with the WSL vhdx location set to `$temp\wslcompact`.
# Temp location resolved to `C:\Users\polarathene\AppData\Local\Temp\wslcompact`
$ wsl --export docker-desktop-data - | wsl --import docker-desktop-data-compacted "$Env:TEMP\wslcompact" -
Import in progress, this may take a few minutes.Program 'wsl.exe' failed to run: Exception of type 'System.OutOfMemoryException' was thrown.At line:1 char:38
+ ... op-data - | wsl --import docker-desktop-data-compacted "$Env:TEMP\wsl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
At line:1 char:1
+ wsl --export docker-desktop-data - | wsl --import docker-desktop-data ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [], ApplicationFailedException
+ FullyQualifiedErrorId : NativeCommandFailed
wsl --export
can export a .vhdx
file instead of a .tar
, but this is a direct copy that loses the sparse size (in my case that used roughly 17GB disk).wsl --import-in-place
but only available for .vhdx
not .tar
exports.wsl --export
+ wsl --import
UPDATE: If I don't use the pipe, the wsl --export
and wsl --import
commands are relatively fast and don't use anywhere near as much memory. I get the expected 1.4GB size as a .tar
file, and after using wsl --import
the new location creates a 1.4GB .vhdx
as well.
Obviously wslcompact
itself would be easier to use, but here's a step-by-step series of commands you can run directly in PowerShell:
# Prepare steps
# Export / Import files will use this location:
$tmp_folder = "$Env:TEMP\wsl-workaround-dir"
# Only required if the `.tar` export folder does not exist:
New-Item -Path "$tmp_folder" -Type Directory -Force
# Grab the vhdx path for docker-desktop-data:
$wsl_distro_path = (Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq 'docker-desktop-data' }).GetValue("BasePath") + "\ext4.vhdx"
# Export as compressed tar, then run export to create the compacted vhdx file:
wsl --shutdown
wsl --export docker-desktop-data "$tmp_folder\exported.tar"
wsl --import workaround-compacted "$tmp_folder\compacted\" "$tmp_folder\exported.tar"
# Overwrite the existing ext4.vhdx for docker-desktop-data:
wsl --shutdown
Move-Item "$tmp_folder\compacted\ext4.vhdx" "$wsl_distro_path" -Force
# Cleanup - These are no longer needed:
wsl --unregister workaround-compacted
remove-item "$tmp_folder/exported.tar" -Force
# Enable sparse again:
wsl --manage docker-desktop-data --set-sparse true
fstrim
I did a trim after all this with another export+import but without the sparse setting applied. Did the docker build, which increased the 1.4GB vhdx to 5GB, and docker system prune -a
afterwards to delete it all.
Interestingly no trim benefit on that docker disk (/dev/sde
), but it claims to have trimmed 1TB from /dev/sdc
(host disk is 500GB):
$ sudo fstrim --all --verbose
/mnt/wsl/docker-desktop-data/isocache: 0 B (0 bytes) trimmed on /dev/sde
/: 1004.6 GiB (1078706663424 bytes) trimmed on /dev/sdc
The vhdx remains at 5GB. Afterwards I made the docker-desktop-data
vhdx sparse once more, and we see the same behaviour:
$ sudo fstrim --all --verbose
/mnt/wsl/docker-desktop-data/isocache: 1005.5 GiB (1079655772160 bytes) trimmed on /dev/sde
/: 1004.6 GiB (1078685446144 bytes) trimmed on /dev/sdc
The space was not reclaimed though π€·ββοΈ
Closing WSL and using wsl --shutdown
, then opening that up again (and starting Docker Desktop after), the trim command can be run again with the same effect. Bit misleading π€
@talves Just finished testing and sparseVhd doesn't work if the vhdx file is in a mechanical HDD. Make sure the vhdx file resides in a SDD in order to see Size on disk
decreasing.
sparseVhd doesn't work if the vhdx file is in a mechanical HDD
Oh. If it's done intentionally, it should be documented.
@polarathene it's not a docker issue. It's just compiling code for Rust and the files it creates (2G) are deleted. That's the reproduction.
@onomatopellan Yeah, it's a Solid State Drive.
The issue might be that it's on a windows 10 OS. I can't confirm that, because it's only people in comments on the release blog saying that. I haven't seen official statements about it.
WSL version: 2.0.1.0
Kernel version: 5.15.123.1-1
WSLg version: 1.0.58
MSRDC version: 1.2.4485
Direct3D version: 1.608.2-61064218
DXCore version: 10.0.25880.1000-230602-1350.main
Windows version: 10.0.19045.3448
I would just like to revert to the latest non pre-release, if that's possible. This has been a loss of time I wish I never tried.
Is your feature request related to a problem? Please describe. I occasionally have workloads that consume large amounts of disk space for temporary use in
/tmp
. For example, transcoding large video files or processing large datasets exported from a database. Since WSL2 stores its filesystem on a.vhdx
, that file grows when the dataset is processed and never releases that space. Also, it doesn't appear to re-use released disk space in the.vhdx
when files are deleted... it seems to prefer to grow the file rather than re-use existing empty space. (I haven't explicitly tested that theory, but my workload deletes temporary files as they are used and I never had enough of them existing simultaneously to reach 250GB, but the size of the.vhdx
eventually expanded to that size.When I'm done with that workload, I have to:
This is annoying since it basically means that my system backups include a huge
.vhdx
file that is mostly empty. Also, until about 2 weeks ago, it was consuming the entire remainder of my system disk. I had only 50GB free, which was enough to handle the workload, but since it continued to grow even after files were removed, that didn't matter. (I figured it was time to upgrade the disk size anyway)Describe the solution you'd like Automatic compaction of the
.vhdx
, or a way to do so while WSL2 is still running so that I can schedule it for frequent cleanups.Describe alternatives you've considered