qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Amos Kong <akong@redhat.com>
To: qemu-devel@nongnu.org
Cc: amit.shah@redhat.com, varadgautam@gmail.com, anthony@codemonkey.ws
Subject: [Qemu-devel] [PATCH RFC 1/2] rng-egd: improve egd backend performance
Date: Mon,  9 Dec 2013 22:10:12 +0800	[thread overview]
Message-ID: <1386598213-8156-2-git-send-email-akong@redhat.com> (raw)
In-Reply-To: <1386598213-8156-1-git-send-email-akong@redhat.com>

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 <akong@redhat.com>
---
 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	other threads:[~2013-12-09 14:10 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-09 14:10 [Qemu-devel] [PATCH RFC 0/2] improve rng-egd perf Amos Kong
2013-12-09 14:10 ` Amos Kong [this message]
2013-12-16 16:36   ` [Qemu-devel] [PATCH RFC 1/2] rng-egd: improve egd backend performance Amit Shah
2013-12-16 23:19     ` Anthony Liguori
2013-12-17  5:52       ` Amit Shah
2013-12-17  7:03         ` Amos Kong
2013-12-17  7:47   ` Markus Armbruster
2013-12-17 10:32     ` Amit Shah
2013-12-18 10:05     ` Giuseppe Scrivano
2013-12-24  9:58       ` Varad Gautam
2014-01-08  9:14       ` Amos Kong
2014-01-08 16:23         ` Amit Shah
2014-01-10  2:30           ` Amos Kong
2013-12-09 14:10 ` [Qemu-devel] [PATCH RFC 2/2] rng-egd: introduce a parameter to set buffer size Amos Kong
2013-12-10 16:58   ` Eric Blake
2013-12-12  2:55     ` Amos Kong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1386598213-8156-2-git-send-email-akong@redhat.com \
    --to=akong@redhat.com \
    --cc=amit.shah@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    --cc=varadgautam@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).