In Linux, how can I zero-out freed memory pages to reduce the size of VM snapshots?
Non-zeroed memory is stored in the snapshot even if that memory has been freed and is no longer used. For example, memory pages freed from the filesystem cache with
sync && echo 3 > /proc/sys/vm/drop_caches
are needlessly stored in the snapshot because they haven't been zeroed.
Update A really horrible solution that appears to work is to malloc+memset memory in a loop until the OOM killer kicks in. This reduces the size of one VM snapshot I tested from about 800MB to about 400MB. Is there a better solution?
Capturing the memory state of the virtual machine lets you revert to a turned on virtual machine state. With nonmemory snapshots, you can only revert to a turned off virtual machine state. Memory snapshots take longer to create than nonmemory snapshots.
If you plan on using VMware snapshots, you should create VMs with a virtual disk size that's smaller than the maximum VMDK size by the amount of the maximum overhead -- e.g., 512 GB - 4GB = 508 GB. Snapshot files are small initially -- 16 MB -- but they grow as the system makes writes to the VM's disk files.
If you want a consistent state you need to select the "Snapshot the virtual machine's memory" option. This will force a "quiesce" on the virtual machine to flush all cached IO to disk. With the VMware Tools (since ESX 3.5u2) you have the option to enable the VSS driver instead of the File System Sync driver.
Do not use a single snapshot for more than 72 hours. The snapshot file continues to grow in size when it is retained for a longer period. This can cause the snapshot storage location to run out of space and impact the system performance.
Something like this will free up disk cache, then alloc&memset the amount of free memory (minus 32MB, as headroom to avoid hitting swap) using dd. Will temporarily make the VM un-CoW memory in case of for example KSM, but will leave (unallocated) memory blocks filled with zeroes, which can then be shared/deduped with other VMs (with KSM) or easily be compressed.
#!/bin/bash
echo 3 > /proc/sys/vm/drop_caches
memfree=$(free -m | awk '/^Mem/ {print $4-32}')
if [ $memfree -gt 0 ]; then
dd if=/dev/zero of=/dev/null bs=${memfree}M count=1
fi
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With