Bug 915381

Summary: virtio-rng is performing poorly
Product: Red Hat Enterprise Linux 7 Reporter: Peter Krempa <pkrempa>
Component: qemu-kvmAssignee: Amos Kong <akong>
Status: CLOSED DUPLICATE QA Contact: Virtualization Bugs <virt-bugs>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.0CC: acathrow, ailan, juzhang, michen, mzhan, qzhang, rhod, virt-maint, wquan, xigao
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-07-11 16:16:03 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 916194, 917953    

Description Peter Krempa 2013-02-25 15:52:12 UTC
Description of problem:
The virtio-rng infrastructure added recently to qemu performs horribly slow and consumes too much cpu.

Version-Release number of selected component (if applicable):
upstream qemu-1.4 or later that is targeted for 7.0
RHEL 6.4 GA guest

How reproducible:
100%

Steps to Reproduce:
1. start a machine with a virtio-rng capable qemu (version 1.4) with the following command line options:
 -object rng-random,id=rng0,filename=/dev/zero -device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x7 (let's call it 'random' backend)
or 
-chardev socket,id=charrng0,host=localhost,port=1234 -object rng-egd,chardev=charrng0,id=rng0 -device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x7 and run a fake egd server "cat /dev/zero |  nc -l -p 1234 | hexdump -v" ( let's call it 'egd' backend)

2. boot the guest and verify that the virtio-rng module is present and /dev/hwrng is accessible

3. try reading bulk amounts from /dev/hwrng using dd (dd if=/dev/hwrng of=/dev/null bs=1M ...)
  
Actual results:
The 'random' backend performs poorly and is able to pass through ~1MiB/s of entropy. While the read operations are active, the qemu process consumes ~140% cpu. (the guest is provided with 4 vCPUs)

With the 'egd' backend the situation is even worse peaking at about 200KiB/s.

Expected results:
One to two orders of magnitude better performance and less cpu consumption.


Additional info:
Tested on a mobile Intel Core i7 cpu in a X220 Thinkpad laptop.

With current upstream libvirt, the desired commandlines can be achieved using:

<devices>
 ...
  <rng model='virtio'>
    <backend model='random'>/dev/zero</backend>
  </rng>

or

  <rng model='virtio'>
    <backend model='egd' type='tcp'>
      <source type='connect' host='localhost' service='1234'/>
    </backend>
  </rng>
</device>

Comment 2 Amit Shah 2013-02-26 06:29:01 UTC
(In reply to comment #0)

> 3. try reading bulk amounts from /dev/hwrng using dd (dd if=/dev/hwrng
> of=/dev/null bs=1M ...)
>   
> Actual results:
> The 'random' backend performs poorly and is able to pass through ~1MiB/s of
> entropy. While the read operations are active, the qemu process consumes
> ~140% cpu. (the guest is provided with 4 vCPUs)

There are lots of misconceptions here.

1. virtio-rng is not a 'serial' interface: if you want throughput, use virtio-net or virtio-serial.  rng is not a general-purpose device.

2. The kernel expects entropy, not a predictable set of bytes from the device.  The kernel conditions its input, and extracts entropy from what it's given.  If you pass 0s, the kernel isn't supposed to blindly take them and treat it as entropy.  The conditioning in the kernel takes up CPU time.

In my view, this is NOTABUG unless you can give a more convincing example.

Comment 3 Peter Krempa 2013-02-26 11:07:06 UTC
(In reply to comment #2)
> (In reply to comment #0)
> 
> > 3. try reading bulk amounts from /dev/hwrng using dd (dd if=/dev/hwrng
> > of=/dev/null bs=1M ...)
> >   
> > Actual results:
> > The 'random' backend performs poorly and is able to pass through ~1MiB/s of
> > entropy. While the read operations are active, the qemu process consumes
> > ~140% cpu. (the guest is provided with 4 vCPUs)
> 
> There are lots of misconceptions here.

I probably did not explain enough why I've done it this way:

> 
> 1. virtio-rng is not a 'serial' interface: if you want throughput, use
> virtio-net or virtio-serial.  rng is not a general-purpose device.

I know it is not. I tried this also with a true (hardware) random number generator that was outputting ~108 KiB/s but when qemu is doing around 0.2kiB/s when using the EGD backend it's not usable. (see below)

> 
> 2. The kernel expects entropy, not a predictable set of bytes from the
> device.  The kernel conditions its input, and extracts entropy from what
> it's given.  If you pass 0s, the kernel isn't supposed to blindly take them
> and treat it as entropy.  The conditioning in the kernel takes up CPU time.

I'm _NOT_ running rngd, so the kernel is not doing anything with the bytes it recieves. When I read the /dev/hwrng device I get the data I push into it in qemu so as of your point 1 it actually does behave as a serial device:

[root@localhost ~]# dd if=/dev/hwrng bs=1k count=1 | xxd
1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied, 5.38908 s, 0.2 kB/s
0000000: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000010: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000020: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000030: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000040: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000050: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000060: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
0000070: 6161 6161 6161 6161 6161 6161 6161 6161  aaaaaaaaaaaaaaaa
(continued)

(produced using a server that speaks the EGD protocol, not only flooding data to the socket)

I'm complainig that when using the EGD backend the performance is really terrible. I'm purposely feeding constant data ([1]) so that the performance of the generator doesn't influence the measurement.

As you can see on the log:
1.) the throughput is terrible -> 0.2KiB/s 
2.) nothing is done with the data, I fed a's in and I got them out.
3.) even with a true random number generator, the performance is still terrible
 
> In my view, this is NOTABUG unless you can give a more convincing example.

As of the default backend, the 1MiB/s might be a reasonable for most of the generators you are able to source. 

As of the EGD backend, the performance is really terrible and the backend is unusable. In libvirt we're planing on adding a server to distribute/multiplex/traffic shape entropy using the EGD protocol, but this is not usable with the poor performance, thus I don't agree with NOTABUG status.

The tests done here are meant to be synthetic.

[1] http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/00000/2000/300/2318/2318.strip.gif

Comment 6 Amos Kong 2014-04-26 03:40:20 UTC
Related bug:

Bug 1008860 - virtio-rng-egd: get data rate <5k/sec from rng device inside guest
(Closed as WONTFIX)

Comment 7 Amos Kong 2014-07-11 16:16:03 UTC

*** This bug has been marked as a duplicate of bug 1008860 ***