[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
- [Qemu-devel] [PATCH 02/15] qemu aio: prepare for supporting selective bypass coroutine, (continued)
- [Qemu-devel] [PATCH 02/15] qemu aio: prepare for supporting selective bypass coroutine, Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 03/15] block: support to bypass qemu coroutinue, Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 04/15] Revert "raw-posix: drop raw_get_aio_fd() since it is no longer used", Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 05/15] dataplane: enable selective bypassing coroutine, Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 06/15] qemu/obj_pool.h: introduce object allocation pool, Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 07/15] dataplane: use object pool to speed up allocation for virtio blk request, Ming Lei, 2014/07/30
- [Qemu-devel] [PATCH 08/15] virtio: decrease size of VirtQueueElement,
Ming Lei <=
[Qemu-devel] [PATCH 09/15] linux-aio: fix submit aio as a batch, Ming Lei, 2014/07/30