libvirt Tuning
The performance of the VMs can be enhanced by applying the following changes. Thanks to the following Reddit post.
Note
Remember that snapshots also include the XML configuration of a domain. Thus, after applying the following changes, create a new snapshot and update it in the ForTrace++ YAML files accordingly.
Most important are the changes described in [Hypervisor Features] and [Timers].
Disk Type
Note
This needs to be enabled during installation.
Use virtio as the disk type to allow para-virtualization of disk access, which reduces overhead.
Warning
This requires driver support when installing a new Windows guest. During partition of the disk in Windows installation, insert the virtio-win drivers ISO in the VM so the disk can be recognized.
After the installation your <disk> XML section should look like this:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' cache='none' io='threads' discard='unmap' iothread='1' queues='6'/>
<source file='/var/lib/libvirt/images/win11.qcow2'/>
<target dev='vda' bus='virtio'/>
<boot order='2'/>
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>
</disk>
Hypervisor Features
Enable all hypervisor features, by copying the following code block into the
<features> section of the VM’s XML file. libvirt might remove some entries at the
first start of the VM.
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vpindex state='on'/>
<synic state='on'/>
<stimer state='on'>
<direct state='on'/>
</stimer>
<reset state='on'/>
<frequencies state='on'/>
<reenlightenment state='on'/>
<tlbflush state='on'/>
<ipi state='on'/>
</hyperv>
Timers
Disable all timers except for the hypervclock in the <clock> section of the XML.
<clock offset='localtime'>
<timer name='rtc' present='no' tickpolicy='catchup'/>
<timer name='pit' present='no' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='kvmclock' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
CPU
CPU pinning can be used to further improve the performance of the VM. This forces each virtual CPU to be pinned to a physical CPU core, reducing the overhead from the kernel constantly swapping virtual CPUs to different threads. The configuration depends on your machine and the configuration of the VM, e.g., how many cores are available in total and how many are mapped to the VM.