qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 4/4] coroutine: pool coroutines to speed up creat


From: Stefan Hajnoczi
Subject: [Qemu-devel] [PATCH v2 4/4] coroutine: pool coroutines to speed up creation
Date: Thu, 12 May 2011 10:54:46 +0100

This patch speeds up coroutine creation by reusing freed coroutines.
When a coroutine terminates it is placed in the pool instead of having
its resources freed.  The next time a coroutine is created it can be
taken straight from the pool and requires no initialization.

Performance results on an Intel Core2 Duo T9400 (2.53GHz) for
./check-coroutine --benchmark-lifecycle 20000000:

  No pooling:    19.5 sec
  With pooling:   1.1 sec

Signed-off-by: Stefan Hajnoczi <address@hidden>
---
 check-coroutine.c    |    2 ++
 qemu-coroutine-int.h |    2 ++
 qemu-coroutine.c     |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 qemu-coroutine.h     |    9 +++++++++
 vl.c                 |    2 ++
 5 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/check-coroutine.c b/check-coroutine.c
index 5a42c49..223c50c 100644
--- a/check-coroutine.c
+++ b/check-coroutine.c
@@ -218,6 +218,8 @@ int main(int argc, char **argv)
     };
     int i;
 
+    qemu_coroutine_init();
+
     if (argc == 3 && strcmp(argv[1], "--benchmark-lifecycle") == 0) {
         benchmark_lifecycle(argv[2]);
         return EXIT_SUCCESS;
diff --git a/qemu-coroutine-int.h b/qemu-coroutine-int.h
index 71c6ee9..b264881 100644
--- a/qemu-coroutine-int.h
+++ b/qemu-coroutine-int.h
@@ -45,6 +45,8 @@ struct Coroutine {
     void *data;
     CoroutineEntry *entry;
 
+    QLIST_ENTRY(Coroutine) pool_next;
+
     jmp_buf env;
 };
 
diff --git a/qemu-coroutine.c b/qemu-coroutine.c
index 80bed14..cff5a4f 100644
--- a/qemu-coroutine.c
+++ b/qemu-coroutine.c
@@ -24,16 +24,35 @@
 #include "qemu-coroutine.h"
 #include "qemu-coroutine-int.h"
 
+enum {
+    /* Maximum free pool size prevents holding too many freed coroutines */
+    POOL_MAX_SIZE = 64,
+};
+
+static QLIST_HEAD(, Coroutine) pool = QLIST_HEAD_INITIALIZER(&pool);
+static unsigned int pool_size;
 static __thread Coroutine leader;
 static __thread Coroutine *current;
 
-static void coroutine_terminate(Coroutine *co)
+static void coroutine_delete(Coroutine *co)
 {
-    trace_qemu_coroutine_terminate(co);
     qemu_free(co->stack);
     qemu_free(co);
 }
 
+static void coroutine_terminate(Coroutine *co)
+{
+    trace_qemu_coroutine_terminate(co);
+
+    if (pool_size < POOL_MAX_SIZE) {
+        QLIST_INSERT_HEAD(&pool, co, pool_next);
+        co->caller = NULL;
+        pool_size++;
+    } else {
+        coroutine_delete(co);
+    }
+}
+
 static Coroutine *coroutine_new(void)
 {
     const size_t stack_size = 4 << 20;
@@ -49,7 +68,15 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry)
 {
     Coroutine *co;
 
-    co = coroutine_new();
+    co = QLIST_FIRST(&pool);
+
+    if (co) {
+        QLIST_REMOVE(co, pool_next);
+        pool_size--;
+    } else {
+        co = coroutine_new();
+    }
+
     co->entry = entry;
 
     return co;
@@ -123,3 +150,19 @@ void *coroutine_fn qemu_coroutine_yield(void)
     self->caller = NULL;
     return coroutine_swap(self, to, NULL);
 }
+
+static void coroutine_free_pool(void)
+{
+    Coroutine *co;
+    Coroutine *tmp;
+
+    QLIST_FOREACH_SAFE(co, &pool, pool_next, tmp) {
+        coroutine_delete(co);
+    }
+    pool_size = 0;
+}
+
+void qemu_coroutine_init(void)
+{
+    atexit(coroutine_free_pool);
+}
diff --git a/qemu-coroutine.h b/qemu-coroutine.h
index b79b4bf..0fae0a4 100644
--- a/qemu-coroutine.h
+++ b/qemu-coroutine.h
@@ -17,6 +17,15 @@
 #include <stdbool.h>
 
 /**
+ * Initialize coroutine implementation
+ *
+ * This function should be called when the program is starting up.  It installs
+ * an atexit(3) handler which will free pooled coroutines when the program
+ * exits.  This keeps valgrind output clean.
+ */
+void qemu_coroutine_init(void);
+
+/**
  * Mark a function that executes in coroutine context
  *
  * Functions that execute in coroutine context cannot be called directly from
diff --git a/vl.c b/vl.c
index 6b9a2f6..7092c9f 100644
--- a/vl.c
+++ b/vl.c
@@ -145,6 +145,7 @@ int main(int argc, char **argv)
 #include "qemu-config.h"
 #include "qemu-objects.h"
 #include "qemu-options.h"
+#include "qemu-coroutine.h"
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
@@ -1975,6 +1976,7 @@ int main(int argc, char **argv, char **envp)
     init_clocks();
 
     qemu_cache_utils_init(envp);
+    qemu_coroutine_init();
 
     QLIST_INIT (&vm_change_state_head);
     os_setup_early_signal_handling();
-- 
1.7.4.4




reply via email to

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