virtio: limit avail bytes lookahead
PATCH v2 1/1 virtio: limit avail bytes lookahead
Commit 0d8d7690850eb0cf2b2b60933cf47669a6b6f18f introduced a regression in virtio-net performance because it looks into the ring aggressively while we really only care about a single packet worth of buffers.
Reported as bugzilla 1066055 in launchpad.
To fix, add parameters limiting lookahead, and
use in virtqueue_avail_bytes.
---
Anthony says he wants to test this, I only compiled this patch.
hw/virtio-rng.c | 12 +++++++++--- hw/virtio-serial-bus.c | 2 +- hw/virtio.c | 15 ++++++++------- hw/virtio.h | 3 ++- 4 files changed, 20 insertions(+), 12 deletions(-)
hw/virtio-rng.c +9 -3
@@ -43,11 +43,11 @@ static bool is_guest_ready(VirtIORNG *vrng)return false; } -static size_t get_request_size (VirtQueue *vq) +static size_t get_request_size (VirtQueue *vq,unsigned quota) {unsigned int in, out; -virtqueue_get_avail_bytes (vq, &in, &out); +virtqueue_get_avail_bytes (vq, &in, &out, quota,0 );return in; }
@@ -84,12 +84,18 @@ static void chr_read(void *opaque, const void *buf, size_t size)static void virtio_rng_process (VirtIORNG *vrng) {size_t size; +unsigned quota;if (!is_guest_ready (vrng)) {return ; } - size =get_request_size (vrng->vq); +if (vrng->quota_remaining <0 ) { + quota =0 ; + }else { + quota =MIN ((uint64_t )vrng->quota_remaining, (uint64_t )UINT32_MAX ); + } + size =get_request_size (vrng->vq, quota); size =MIN (vrng->quota_remaining, size);if (size) {rng_backend_request_entropy (vrng->rng, size, chr_read, vrng);
hw/virtio-serial-bus.c +1 -1
@@ -306,7 +306,7 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)if (use_multiport (port->vser) && !port->guest_connected) {return 0 ; } -virtqueue_get_avail_bytes (vq, &bytes,NULL ); +virtqueue_get_avail_bytes (vq, &bytes,NULL ,4096 ,0 );return bytes; }
hw/virtio.c +8 -7
@@ -336,7 +336,8 @@ static unsigned virtqueue_next_desc(hwaddr desc_pa, }void virtqueue_get_avail_bytes (VirtQueue *vq,unsigned int *in_bytes, -unsigned int *out_bytes) +unsigned int *out_bytes, +unsigned max_in_bytes,unsigned max_out_bytes) {unsigned int idx;unsigned int total_bufs, in_total, out_total;
@@ -385,6 +386,9 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, }else { out_total +=vring_desc_len (desc_pa, i); } +if (in_total >= max_in_bytes && out_total >= max_out_bytes) { + goto done; + } }while ((i =virtqueue_next_desc (desc_pa, i, max)) != max);if (!indirect)
@@ -392,6 +396,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,else total_bufs++; } +done:if (in_bytes) { *in_bytes = in_total; }
@@ -405,12 +410,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, {unsigned int in_total, out_total; -virtqueue_get_avail_bytes (vq, &in_total, &out_total); -if ((in_bytes && in_bytes < in_total) - || (out_bytes && out_bytes < out_total)) { -return 1 ; - } -return 0 ; +virtqueue_get_avail_bytes (vq, &in_total, &out_total, in_bytes, out_bytes); +return in_bytes <= in_total && out_bytes <= out_total; } void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
hw/virtio.h +2 -1
@@ -150,7 +150,8 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);int virtqueue_avail_bytes (VirtQueue *vq,unsigned int in_bytes,unsigned int out_bytes);void virtqueue_get_avail_bytes (VirtQueue *vq,unsigned int *in_bytes, -unsigned int *out_bytes); +unsigned int *out_bytes, +unsigned max_in_bytes,unsigned max_out_bytes);void virtio_notify (VirtIODevice *vdev,VirtQueue *vq);
Signature · 1 line
MST
Anthony Liguori
AppliedQuoted 9 lines · Michael S. Tsirkin
Commit
0d8d7690850eb0cf2b2b60933cf47669a6b6f18fintroduced a regression in virtio-net performance because it looks into the ring aggressively while we really only care about a single packet worth of buffers.
Reported as bugzilla 1066055 in launchpad.To fix, add parameters limiting lookahead, and
use invirtqueue_avail_bytes.
Quoted 7 lines
Signed-off-by Michael S. Tsirkin <[email protected]>Reported-by Edivaldo de Araujo Pereira <[email protected]>Reviewed-by Stefan Hajnoczi <[email protected]>---
Anthony says he wants to test this, I only compiled this patch.
I tested it and it works.
Applied. Thanks.
Regards,
Anthony Liguori
Quoted 121 lines
hw/virtio-rng.c | 12 +++++++++--- hw/virtio-serial-bus.c | 2 +- hw/virtio.c | 15 ++++++++------- hw/virtio.h | 3 ++- 4 files changed, 20 insertions(+), 12 deletions(-)hw/virtio-rng.c +9
-3@@ -43,11 +43,11 @@ static bool is_guest_ready(VirtIORNG *vrng)return false; } -static size_t get_request_size (VirtQueue *vq) +static size_t get_request_size (VirtQueue *vq,unsigned quota) {unsigned int in, out; -virtqueue_get_avail_bytes (vq, &in, &out); +virtqueue_get_avail_bytes (vq, &in, &out, quota,0 );return in; }@@ -84,12 +84,18 @@ static void chr_read(void *opaque, const void *buf, size_t size)static void virtio_rng_process (VirtIORNG *vrng) {size_t size; +unsigned quota;if (!is_guest_ready (vrng)) {return ; } - size =get_request_size (vrng->vq); +if (vrng->quota_remaining <0 ) { + quota =0 ; + }else { + quota =MIN ((uint64_t )vrng->quota_remaining, (uint64_t )UINT32_MAX ); + } + size =get_request_size (vrng->vq, quota); size =MIN (vrng->quota_remaining, size);if (size) {rng_backend_request_entropy (vrng->rng, size, chr_read, vrng);hw/virtio-serial-bus.c +1
-1@@ -306,7 +306,7 @@ size_t virtio_serial_guest_ready(VirtIOSerialPort *port)if (use_multiport (port->vser) && !port->guest_connected) {return 0 ; } -virtqueue_get_avail_bytes (vq, &bytes,NULL ); +virtqueue_get_avail_bytes (vq, &bytes,NULL ,4096 ,0 );return bytes; }hw/virtio.c +8
-7@@ -336,7 +336,8 @@ static unsigned virtqueue_next_desc(hwaddr desc_pa, }void virtqueue_get_avail_bytes (VirtQueue *vq,unsigned int *in_bytes, -unsigned int *out_bytes) +unsigned int *out_bytes, +unsigned max_in_bytes,unsigned max_out_bytes) {unsigned int idx;unsigned int total_bufs, in_total, out_total;@@ -385,6 +386,9 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, }else { out_total +=vring_desc_len (desc_pa, i); } +if (in_total >= max_in_bytes && out_total >= max_out_bytes) { + goto done; + } }while ((i =virtqueue_next_desc (desc_pa, i, max)) != max);if (!indirect)@@ -392,6 +396,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,else total_bufs++; } +done:if (in_bytes) { *in_bytes = in_total; }@@ -405,12 +410,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes, {unsigned int in_total, out_total; -virtqueue_get_avail_bytes (vq, &in_total, &out_total); -if ((in_bytes && in_bytes < in_total) - || (out_bytes && out_bytes < out_total)) { -return 1 ; - } -return 0 ; +virtqueue_get_avail_bytes (vq, &in_total, &out_total, in_bytes, out_bytes); +return in_bytes <= in_total && out_bytes <= out_total; } void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,hw/virtio.h +2
-1@@ -150,7 +150,8 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);int virtqueue_avail_bytes (VirtQueue *vq,unsigned int in_bytes,unsigned int out_bytes);void virtqueue_get_avail_bytes (VirtQueue *vq,unsigned int *in_bytes, -unsigned int *out_bytes); +unsigned int *out_bytes, +unsigned max_in_bytes,unsigned max_out_bytes);void virtio_notify (VirtIODevice *vdev,VirtQueue *vq);Signature · 1 line
MST