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
next prev parent 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).