Why is QEMU so slow even with KVM

I've been working with QEMU for some time now, and from my experience I see it being very slow compared to other VM tools like VirtualBox or VMware.

Even enabling KVM isn't much of a benefit to me. Many people say I might have the worst hardware configuration to which I disagree. VirtualBox and VMware work pretty well for the same hardware. Also I didn't face it on a single system. I tried it on multiple system.

To make my point even clearer, I created the same VM configuration with the same amount of RAM and other things identical as far as I could. Still it seems QEMU is too slow. Especially if I run the VM in GUI mode. For example, if I run Ubuntu in text mode, it's very fast. But when I run Ubuntu in GUI mode, it's much too slow. What is the reason for QEMU being slow? How is it different from VMware or VirtualBox?

I start QEMU using:

qemu-system-i386 -enable-kvm -hda Ubuntu.img -monitor stdio

In the monitor if I run the command info kvm, it says kvm is enabled. Also I tested QEMU on Ubuntu 12.04, 13.10, and 14.04. As guest I run Windows XP and Ubuntu 12.04. I tested with both the 32-bit and 64-bit hosts, but the guest OS was always 32-bit.

Also I did run QEMU with no other existing virtualization tool in the system. My system configuration is good enough with 8GB RAM and Intel Core i3-2100 CPU @ 3.10GHz × 4.


Solution 1:

For what it's worth, qemu was running very slowly on my Ubuntu 14.04 installation. I installed qemu-kvm after installing qemu, and started the program with following command:

kvm -cdrom xxxx.iso -m 700 -boot d

The difference was amazing, and runs very fast now.

Solution 2:

Do you have to use -hda or the stdio IO call? Also note that you will need to add the -enable-kvm flag at a minimum, but I would encourage you to first try installing virt-manager and/or use libvirt as it will fully configure qemu in a way to support good performance.

qemu always uses the most compatible configuration by default, but can easily get within a few percentage points of bare metal performance if configured properly.

As an example on how many options may be needed for an optimal install here is is the contents of the /proc/$pid/cmdline from a VM I just spun up.

qemu-system-x86_64
-enable-kvm
-name guest=ubuntu16.04_32_bit_test,debug-threads=on
-S
-object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-ubuntu16.04_32_bit_t/master-key.aes
-machine pc-i440fx-zesty,accel=kvm,usb=off,dump-guest-core=off
-cpu Skylake-Client
-m 1024
-realtime mlock=off
-smp 1,sockets=1,cores=1,threads=1
-uuid 4aaf9c8f-f8b5-477b-ac18-d273318dfe90
-no-user-config
-nodefaults
-chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-1-ubuntu16.04_32_bit_t/monitor.sock,server,nowait
-mon chardev=charmonitor,id=monitor,mode=control
-rtc base=utc,driftfix=slew
-global kvm-pit.lost_tick_policy=discard
-no-hpet
-no-reboot
-global PIIX4_PM.disable_s3=1
-global PIIX4_PM.disable_s4=1
-boot strict=on
-device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7
-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5
-device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1
-device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x5.0x2
-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6
-drive file=/var/lib/libvirt/images/ubuntu16.04_32_bit_test.qcow2,format=qcow2,if=none,id=drive-virtio-disk0
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x7,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=2
-drive file=/home/gdahlman/Downloads/ubuntu-16.04.2-server-i386.iso,format=raw,if=none,id=drive-ide0-0-0,readonly=on
-device ide-cd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1
-netdev tap,fd=26,id=hostnet0,vhost=on,vhostfd=28
-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:22:78:27,bus=pci.0,addr=0x3
-chardev pty,id=charserial0-deviceisa-serial,chardev=charserial0,id=serial0
-chardev spicevmc,id=charchannel0,name=vdagent
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0
-device usb-tablet,id=input0,bus=usb.0,port=1
-spice port=5900,addr=127.0.0.1,disable-ticketing,image-compression=off,seamless-migration=on
-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=16,max_outputs=1,bus=pci.0,addr=0x2
-device intel-hda,id=sound0,bus=pci.0,addr=0x4
-device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0
-chardev spicevmc,id=charredir0,name=usbredir
-device usb-redir,chardev=charredir0,id=redir0,bus=usb.0,port=2
-chardev spicevmc,id=charredir1,name=usbredir
-device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=3
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x8
-msg timestamp=on
root@rodin

Using qemu from the command line will work, but it will not be high performance.

The libvirt virt-install command will help you with this from the command line and it's --os-variant flag will take care of most of the quirks and optimizations for you.