by on October 2, 2014, in

Compacting Client Hyper-V VHDX Files

Virtual hard disks have the same tendency to grow in size as regular disks have to fill up. Deduplication is a great way to battle this, but unfortunately it is not available for Windows 8 Client Hyper-V. I know that hacks are available describing how to transfer the relevant DLLs from Server 2012 but I value my data too much to try that. The only thing left in order to regain valuable (SSD) disk space is to compact the VHDX. That, however, is more difficult than it should be.

This article shows how to compact Windows VMs. For a description of how to compact Ubuntu Linux VMs take a look at this post.

Start Inside

Before bringing out the heavy guns do the obvious:

  • Make sure KB2852386 is installed
  • Run Disk Cleanup with admin permissions

These simple things unearth treasures like the following:

Windows 7 Disk Cleanup

Do a full reboot after running Disk Cleanup because part of the removal happens when the system next starts up.

Zero, Defragment and Shrink

Zero

Run Sysinternals’ Sdelete tool to zero all the deleted bits on disk:

sdelete -s -z c:

Defragment

While defragmenting is not strictly necessary it increases the chances that the shrinking process in the next step is successful.

Shrink

Go to Disk Management and shrink your partition(s) as much as possible. This is the most important part. Without this Hyper-V unfortunately is not able to compact the VHDX significantly.

Compact VHDX from the GUI

When you go to a virtual machine’s settings and edit the hard drive, you are presented with a dialog box offering to compact the disk:

Hyper-V - Edit Virtual Hard Disk - Compact

That is exactly what you want. You select it, click next and … the wizard finishes after a few (too few) seconds and the VHDX size remains unchanged.

Compact VHDX from PowerShell

I am not a big fan of dumbing down or even breaking the UI by making relevant functionality only available through PowerShell as seems to be the trend these days. This seems to be such a case. For some strange reason the Compact VHDX UI does nothing and you have to resort to PowerShell to do the job. Sad.

The relevant command is Optimize-VHD. In order for the optimization to succeed the virtual hard disk needs to be mounted first with Mount-VHD (both commands work on VHD and VHDX files).

Automation

You probably have more than one virtual machine on your PC or laptop. In order to shrink them all manually shut them down first. Then run the following command, replacing D:\VMs with the base path for your VHDX files:

gci -File -Filter *.vhd* -Path D:\VMs -Recurse | % {Mount-VHD $_.FullName -ReadOnly; Optimize-VHD $_.FullName -Mode full; Dismount-VHD $_.FullName}

Errors

The PowerShell code may report errors. Possible causes include

  • The VHDX is in use (the VM is probably not turned off)
  • The VHDX is a differencing disk and the parent disk is not properly connected any more

Analysis & Conclusion

The implementation of dynamically expanding virtual disks in Hyper-V leaves room for improvement, at least when looking at disk space requirements. Reclaiming (host) disk space by compacting the VHDX files succeeds only when there is unpartitioned space at the end of the virtual hard disk. That typically involves shrinking a partition from inside the VM.

A more efficient implementation could make use of the trim command to keep track which parts of a disk are not needed any more and use that information to reduce the size of the VHDX upon request.

Lacking such a more advanced algorithm be prepared to throw disk space at the problem of expanding VHDX files that won’t compact (much). Host-based deduplication would be the answer – if only it were available on client versions of Windows.

Previous Article VCNRW - Your Friendly Local Virtualization Community
Next Article Splunk Revolution Award