qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 08/15] virtio: decrease size of VirtQueueElement


From: Ming Lei
Subject: [Qemu-devel] [PATCH 08/15] virtio: decrease size of VirtQueueElement
Date: Wed, 30 Jul 2014 19:39:41 +0800

VirtQueueElement is used in performance senstive path, so cut
its size by half to speed up its allocation and decrease memory
footprint in the dataplane I/O path.

Signed-off-by: Ming Lei <address@hidden>
---
 hw/net/virtio-net.c         |    4 +++-
 hw/virtio/dataplane/vring.c |   23 ++++++++++++++++++-----
 hw/virtio/virtio.c          |   23 ++++++++++++++++-------
 include/hw/virtio/virtio.h  |   13 +++++++++----
 4 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 268eff9..c842697 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1010,7 +1010,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, 
const uint8_t *buf, size_t
     while (offset < size) {
         VirtQueueElement elem;
         int len, total;
-        const struct iovec *sg = elem.in_sg;
+        const struct iovec *sg;
 
         total = 0;
 
@@ -1025,6 +1025,8 @@ static ssize_t virtio_net_receive(NetClientState *nc, 
const uint8_t *buf, size_t
             exit(1);
         }
 
+        sg = elem.in_sg;
+
         if (elem.in_num < 1) {
             error_report("virtio-net receive queue contains no in buffers");
             exit(1);
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 67cb2b8..502c999 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -164,12 +164,12 @@ static int get_desc(Vring *vring, VirtQueueElement *elem,
 
     if (desc->flags & VRING_DESC_F_WRITE) {
         num = &elem->in_num;
-        iov = &elem->in_sg[*num];
-        addr = &elem->in_addr[*num];
+        iov = &elem->sg[elem->num];
+        addr = &elem->addr[elem->num];
     } else {
         num = &elem->out_num;
-        iov = &elem->out_sg[*num];
-        addr = &elem->out_addr[*num];
+        iov = &elem->sg[elem->num];
+        addr = &elem->addr[elem->num];
 
         /* If it's an output descriptor, they're all supposed
          * to come before any input descriptors. */
@@ -198,6 +198,7 @@ static int get_desc(Vring *vring, VirtQueueElement *elem,
     iov->iov_len = desc->len;
     *addr = desc->addr;
     *num += 1;
+    elem->num++;
     return 0;
 }
 
@@ -289,6 +290,15 @@ static void vring_unmap_element(VirtQueueElement *elem)
     }
 }
 
+static void update_elem(VirtQueueElement *elem)
+{
+    elem->out_sg = &elem->sg[0];
+    elem->out_addr = &elem->addr[0];
+
+    elem->in_sg = &elem->sg[elem->out_num];
+    elem->in_addr = &elem->addr[elem->out_num];
+}
+
 /* This looks in the virtqueue and for the first available buffer, and converts
  * it to an iovec for convenient access.  Since descriptors consist of some
  * number of output then some number of input descriptors, it's actually two
@@ -309,7 +319,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
     int ret;
 
     /* Initialize elem so it can be safely unmapped */
-    elem->in_num = elem->out_num = 0;
+    elem->num = elem->in_num = elem->out_num = 0;
 
     /* If there was a fatal error then refuse operation */
     if (vring->broken) {
@@ -389,11 +399,14 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
         i = desc.next;
     } while (desc.flags & VRING_DESC_F_NEXT);
 
+    update_elem(elem);
+
     /* On success, increment avail index. */
     vring->last_avail_idx++;
     return head;
 
 out:
+    update_elem(elem);
     assert(ret < 0);
     if (ret == -EFAULT) {
         vring->broken = true;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 5c98180..db42cd0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -463,7 +463,7 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
         return 0;
 
     /* When we start there are none of either input nor output. */
-    elem->out_num = elem->in_num = 0;
+    elem->num = elem->out_num = elem->in_num = 0;
 
     max = vq->vring.num;
 
@@ -489,21 +489,25 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
         struct iovec *sg;
 
         if (vring_desc_flags(vdev, desc_pa, i) & VRING_DESC_F_WRITE) {
-            if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
+            if (elem->in_num >= ARRAY_SIZE(elem->sg)) {
                 error_report("Too many write descriptors in indirect table");
                 exit(1);
             }
-            elem->in_addr[elem->in_num] = vring_desc_addr(vdev, desc_pa, i);
-            sg = &elem->in_sg[elem->in_num++];
+            elem->addr[elem->num] = vring_desc_addr(vdev, desc_pa, i);
+            sg = &elem->sg[elem->num];
+            elem->in_num++;
         } else {
-            if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
+            if (elem->out_num >= ARRAY_SIZE(elem->sg)) {
                 error_report("Too many read descriptors in indirect table");
                 exit(1);
             }
-            elem->out_addr[elem->out_num] = vring_desc_addr(vdev, desc_pa, i);
-            sg = &elem->out_sg[elem->out_num++];
+            elem->addr[elem->num] = vring_desc_addr(vdev, desc_pa, i);
+            sg = &elem->sg[elem->num];
+            elem->out_num++;
         }
 
+        elem->num++;
+
         sg->iov_len = vring_desc_len(vdev, desc_pa, i);
 
         /* If we've got too many, that implies a descriptor loop. */
@@ -513,6 +517,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
         }
     } while ((i = virtqueue_next_desc(vdev, desc_pa, i, max)) != max);
 
+    elem->out_sg = &elem->sg[0];
+    elem->out_addr = &elem->addr[0];
+    elem->in_sg = &elem->sg[elem->out_num];
+    elem->in_addr = &elem->addr[elem->out_num];
+
     /* Now map what we have collected */
     virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
     virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index a60104c..943e72f 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -84,12 +84,17 @@ typedef struct VirtQueue VirtQueue;
 typedef struct VirtQueueElement
 {
     unsigned int index;
+    unsigned int num;
     unsigned int out_num;
     unsigned int in_num;
-    hwaddr in_addr[VIRTQUEUE_MAX_SIZE];
-    hwaddr out_addr[VIRTQUEUE_MAX_SIZE];
-    struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
-    struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
+
+    hwaddr *in_addr;
+    hwaddr *out_addr;
+    struct iovec *in_sg;
+    struct iovec *out_sg;
+
+    hwaddr addr[VIRTQUEUE_MAX_SIZE];
+    struct iovec sg[VIRTQUEUE_MAX_SIZE];
 } VirtQueueElement;
 
 #define VIRTIO_PCI_QUEUE_MAX 64
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]