qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

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