[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH RFC 1/2] rng-egd: improve egd backend performance
From: |
Amos Kong |
Subject: |
[Qemu-devel] [PATCH RFC 1/2] rng-egd: improve egd backend performance |
Date: |
Mon, 9 Dec 2013 22:10:12 +0800 |
Bugzilla: https://bugs.launchpad.net/qemu/+bug/1253563
We have a requests queue to cache the random data, but the second
will come in when the first request is returned, so we always
only have one items in the queue. It effects the performance.
This patch changes the IOthread to fill a fixed buffer with
random data from egd socket, request_entropy() will return
data to virtio queue if buffer has available data.
(test with a fast source, disguised egd socket)
# cat /dev/urandom | nc -l localhost 8003
# qemu .. -chardev socket,host=localhost,port=8003,id=chr0 \
-object rng-egd,chardev=chr0,id=rng0,buf_size=1024 \
-device virtio-rng-pci,rng=rng0
bytes kb/s
------ ----
131072 -> 835
65536 -> 652
32768 -> 356
16384 -> 182
8192 -> 99
4096 -> 52
2048 -> 30
1024 -> 15
512 -> 8
256 -> 4
128 -> 3
64 -> 2
Signed-off-by: Amos Kong <address@hidden>
---
backends/rng-egd.c | 131 +++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 111 insertions(+), 20 deletions(-)
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 62226d5..d317c61 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -18,6 +18,8 @@
#define TYPE_RNG_EGD "rng-egd"
#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
+#define BUFFER_SIZE 65536
+
typedef struct RngEgd
{
RngBackend parent;
@@ -28,6 +30,7 @@ typedef struct RngEgd
EntropyReceiveFunc *receive_entropy;
GSList *requests;
void *opaque;
+ size_t req_size;
} RngEgd;
typedef struct RngRequest
@@ -37,9 +40,57 @@ typedef struct RngRequest
size_t size;
} RngRequest;
-static void rng_egd_request_entropy(RngBackend *b, size_t size,
- EntropyReceiveFunc *receive_entropy,
- void *opaque)
+
+static void rng_egd_free_request(RngRequest *req)
+{
+ g_free(req->data);
+ g_free(req);
+}
+
+static int get_available_data_size(RngEgd *s)
+{
+ GSList *i;
+ RngRequest *req;
+ int total = 0;
+
+ for (i = s->requests; i; i = i->next) {
+ req = i->data;
+ total += req->offset;
+ }
+ return total;
+}
+
+static int get_free_buf_size(RngEgd *s)
+{
+
+ GSList *i;
+ RngRequest *req;
+ int total = 0;
+
+ for (i = s->requests; i; i = i->next) {
+ req = i->data;
+ total += req->size - req->offset;
+ }
+ return total;
+}
+
+static int get_total_buf_size(RngEgd *s)
+{
+
+ GSList *i;
+ RngRequest *req;
+ int total = 0;
+
+ for (i = s->requests; i; i = i->next) {
+ req = i->data;
+ total += req->size;
+ }
+ return total;
+}
+
+static void rng_egd_append_request(RngBackend *b, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
{
RngEgd *s = RNG_EGD(b);
RngRequest *req;
@@ -69,21 +120,60 @@ static void rng_egd_request_entropy(RngBackend *b, size_t
size,
s->requests = g_slist_append(s->requests, req);
}
-static void rng_egd_free_request(RngRequest *req)
+
+static void rng_egd_expend_request(RngEgd *s, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
{
- g_free(req->data);
- g_free(req);
+ GSList *cur = s->requests;
+
+ while (size > 0 && cur) {
+ RngRequest *req = cur->data;
+ int len = MIN(size, req->offset);
+
+ s->receive_entropy(s->opaque, req->data, len);
+ req->offset -= len;
+ size -= len;
+ cur = cur->next;
+ }
+}
+
+static void rng_egd_request_entropy(RngBackend *b, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
+{
+ RngEgd *s = RNG_EGD(b);
+
+ s->receive_entropy = receive_entropy;
+ s->opaque = opaque;
+ s->req_size += size;
+
+ if (get_available_data_size(s) >= size) {
+ rng_egd_expend_request(s, size, receive_entropy, opaque);
+ s->req_size -= size;
+ }
+
+ int total_size = get_total_buf_size(s);
+
+ while (total_size < BUFFER_SIZE) {
+ int add_size = MIN(BUFFER_SIZE - total_size, 255);
+ total_size += add_size;
+ rng_egd_append_request(b, add_size, receive_entropy, opaque);
+ }
}
static int rng_egd_chr_can_read(void *opaque)
{
RngEgd *s = RNG_EGD(opaque);
- GSList *i;
int size = 0;
- for (i = s->requests; i; i = i->next) {
- RngRequest *req = i->data;
- size += req->size - req->offset;
+ size = get_free_buf_size(s);
+
+ if (size == 0 && s->req_size > 0) {
+ int len = MIN(s->req_size, get_available_data_size(s));
+ rng_egd_expend_request(s, len, s->receive_entropy, opaque);
+ s->req_size -= len;
+ size = get_free_buf_size(s);
}
return size;
@@ -93,24 +183,25 @@ static void rng_egd_chr_read(void *opaque, const uint8_t
*buf, int size)
{
RngEgd *s = RNG_EGD(opaque);
size_t buf_offset = 0;
+ int len;
+ GSList *cur = s->requests;
while (size > 0 && s->requests) {
- RngRequest *req = s->requests->data;
- int len = MIN(size, req->size - req->offset);
+ RngRequest *req = cur->data;
+ len = MIN(size, req->size - req->offset);
memcpy(req->data + req->offset, buf + buf_offset, len);
buf_offset += len;
req->offset += len;
size -= len;
-
- if (req->offset == req->size) {
- s->requests = g_slist_remove_link(s->requests, s->requests);
-
- s->receive_entropy(s->opaque, req->data, req->size);
-
- rng_egd_free_request(req);
- }
+ cur = cur->next;
}
+ if (s->req_size > 0) {
+ len = MIN(s->req_size, get_available_data_size(s));
+ rng_egd_expend_request(s, len, s->receive_entropy, opaque);
+ s->req_size -= len;
+ }
+
}
static void rng_egd_free_requests(RngEgd *s)
--
1.8.3.1
[Qemu-devel] [PATCH RFC 2/2] rng-egd: introduce a parameter to set buffer size, Amos Kong, 2013/12/09