qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH ] test-coroutine: test cost introduced by coroutine


From: Ming Lei
Subject: [Qemu-devel] [PATCH ] test-coroutine: test cost introduced by coroutine
Date: Mon, 11 Aug 2014 19:59:05 +0800

This test uses getppid() syscall to simulate single operation
run inside coroutine, and compare how many operations done per
second between using coroutine and not using coroutine to
evalute cost introduced by running operation via coroutine.

Paolo introduced 'baseline test' for computing the cost
of coroutine operations, and it may be not enough since coroutine
switches stack for running task and this cost won't be considered
at all, and in reality most of actual corotine cases can't avoid
stack use at all. So this patch uses getppid() syscall to simulte
operation running from coroutine:

        - syscall and related stack operations can't be optimized by compiler
        - push to/pop from user space stack introduced by calling syscall,
        such as for save/restore context
    - also it isn't unusual to call syscall from coroutine

For example, here are the results on my machine when treating 1
getppid() as one operation:

        - Run operation 60000000 iterations(1 getppid() per operation) without 
using
        coroutine: 3.517642 s, 17056K operations/s
        - Run operation 60000000 iterations(1 getppid() per operation) using
        coroutine: 11.157434 s, 5377K operations/s
        - Coroutine introduced cost: 68%

If running 30 getppid() in one operation:

        - Run operation 60000000 iterations(30 getppid() per operation) without 
using
        coroutine: 3.264977 s, 612K operations/s
        - Run operation 60000000 iterations(30 getppid() per operation) using
        coroutine: 3.733169 s, 535K operations/s
        - Coroutine introduced cost: %12

So in some situations, the cost introduced by coroutine isn't too small
to be ignored.

Signed-off-by: Ming Lei <address@hidden>
---
 tests/test-coroutine.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
index 6e634f4..6fa7d40 100644
--- a/tests/test-coroutine.c
+++ b/tests/test-coroutine.c
@@ -311,6 +311,57 @@ static void perf_baseline(void)
         maxcycles, duration);
 }
 
+static __attribute__((noinline)) void perf_cost_run_one(void *opaque)
+{
+    unsigned long *cnt = opaque;
+    unsigned long i = 0;
+
+    while (i++ < *cnt) {
+        getppid();
+    }
+}
+
+static long perf_cost_run(unsigned long maxcycles, unsigned long cnt,
+                          bool use_co)
+{
+    unsigned long i = 0;
+    double duration;
+    unsigned long ops;
+
+    g_test_timer_start();
+    while (i++ < maxcycles) {
+        if (!use_co) {
+            perf_cost_run_one(&cnt);
+        } else {
+            Coroutine *co = qemu_coroutine_create(perf_cost_run_one);
+            qemu_coroutine_enter(co, &cnt);
+        }
+    }
+    duration = g_test_timer_elapsed();
+    ops = (long)(maxcycles / (duration * 1000));
+
+    g_test_message("Run operation %lu iterations(%lu getppid() per operation) "
+                   "%s: %f s, %luK operations/s",
+                   maxcycles, cnt,
+                   use_co ? "using coroutine" : "without using coroutine",
+                   duration, ops);
+
+    return ops;
+}
+
+static void perf_cost(void)
+{
+    unsigned long maxcycles = 60000000;
+    unsigned long cnt = 1;
+    long ops_base, ops_co;
+
+    ops_base = perf_cost_run(maxcycles / cnt, cnt, false);
+    ops_co = perf_cost_run(maxcycles / cnt, cnt, true);
+
+    g_test_message("Coroutine introduced cost: %lu%%",
+                    (ops_base - ops_co) * 100 / ops_base);
+}
+
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
@@ -325,6 +376,7 @@ int main(int argc, char **argv)
         g_test_add_func("/perf/nesting", perf_nesting);
         g_test_add_func("/perf/yield", perf_yield);
         g_test_add_func("/perf/function-call", perf_baseline);
+        g_test_add_func("/perf/cost", perf_cost);
     }
     return g_test_run();
 }
-- 
1.7.9.5




reply via email to

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