Message ID | 1407758345-2508-1-git-send-email-ming.lei@canonical.com |
---|---|
State | New |
Headers | show |
On Mon, Aug 11, 2014 at 7:59 PM, Ming Lei <ming.lei@canonical.com> wrote: > 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. Please ignore this one, and I have better and simper patch to figure out coroutine cost. Thanks,
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(); }
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 <ming.lei@canonical.com> --- tests/test-coroutine.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)