Home | History | Annotate | Line # | Download | only in test
      1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
      2  *
      3  * Permission is hereby granted, free of charge, to any person obtaining a copy
      4  * of this software and associated documentation files (the "Software"), to
      5  * deal in the Software without restriction, including without limitation the
      6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      7  * sell copies of the Software, and to permit persons to whom the Software is
      8  * furnished to do so, subject to the following conditions:
      9  *
     10  * The above copyright notice and this permission notice shall be included in
     11  * all copies or substantial portions of the Software.
     12  *
     13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     19  * IN THE SOFTWARE.
     20  */
     21 
     22 #include "task.h"
     23 #include "uv.h"
     24 
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 
     28 #define NUM_PINGS (1000 * 1000)
     29 
     30 struct ctx {
     31   uv_loop_t loop;
     32   uv_thread_t thread;
     33   uv_async_t main_async;    /* wake up main thread */
     34   uv_async_t worker_async;  /* wake up worker */
     35   unsigned int nthreads;
     36   unsigned int main_sent;
     37   unsigned int main_seen;
     38   unsigned int worker_sent;
     39   unsigned int worker_seen;
     40 };
     41 
     42 
     43 static void worker_async_cb(uv_async_t* handle) {
     44   struct ctx* ctx = container_of(handle, struct ctx, worker_async);
     45 
     46   ASSERT(0 == uv_async_send(&ctx->main_async));
     47   ctx->worker_sent++;
     48   ctx->worker_seen++;
     49 
     50   if (ctx->worker_sent >= NUM_PINGS)
     51     uv_close((uv_handle_t*) &ctx->worker_async, NULL);
     52 }
     53 
     54 
     55 static void main_async_cb(uv_async_t* handle) {
     56   struct ctx* ctx = container_of(handle, struct ctx, main_async);
     57 
     58   ASSERT(0 == uv_async_send(&ctx->worker_async));
     59   ctx->main_sent++;
     60   ctx->main_seen++;
     61 
     62   if (ctx->main_sent >= NUM_PINGS)
     63     uv_close((uv_handle_t*) &ctx->main_async, NULL);
     64 }
     65 
     66 
     67 static void worker(void* arg) {
     68   struct ctx* ctx = arg;
     69   ASSERT(0 == uv_async_send(&ctx->main_async));
     70   ASSERT(0 == uv_run(&ctx->loop, UV_RUN_DEFAULT));
     71   uv_loop_close(&ctx->loop);
     72 }
     73 
     74 
     75 static int test_async(int nthreads) {
     76   struct ctx* threads;
     77   struct ctx* ctx;
     78   uint64_t time;
     79   int i;
     80 
     81   threads = calloc(nthreads, sizeof(threads[0]));
     82   ASSERT_NOT_NULL(threads);
     83 
     84   for (i = 0; i < nthreads; i++) {
     85     ctx = threads + i;
     86     ctx->nthreads = nthreads;
     87     ASSERT(0 == uv_loop_init(&ctx->loop));
     88     ASSERT(0 == uv_async_init(&ctx->loop, &ctx->worker_async, worker_async_cb));
     89     ASSERT(0 == uv_async_init(uv_default_loop(),
     90                               &ctx->main_async,
     91                               main_async_cb));
     92     ASSERT(0 == uv_thread_create(&ctx->thread, worker, ctx));
     93   }
     94 
     95   time = uv_hrtime();
     96 
     97   ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
     98 
     99   for (i = 0; i < nthreads; i++)
    100     ASSERT(0 == uv_thread_join(&threads[i].thread));
    101 
    102   time = uv_hrtime() - time;
    103 
    104   for (i = 0; i < nthreads; i++) {
    105     ctx = threads + i;
    106     ASSERT(ctx->worker_sent == NUM_PINGS);
    107     ASSERT(ctx->worker_seen == NUM_PINGS);
    108     ASSERT(ctx->main_sent == (unsigned int) NUM_PINGS);
    109     ASSERT(ctx->main_seen == (unsigned int) NUM_PINGS);
    110   }
    111 
    112   printf("async%d: %.2f sec (%s/sec)\n",
    113          nthreads,
    114          time / 1e9,
    115          fmt(NUM_PINGS / (time / 1e9)));
    116 
    117   free(threads);
    118 
    119   MAKE_VALGRIND_HAPPY();
    120   return 0;
    121 }
    122 
    123 
    124 BENCHMARK_IMPL(async1) {
    125   return test_async(1);
    126 }
    127 
    128 
    129 BENCHMARK_IMPL(async2) {
    130   return test_async(2);
    131 }
    132 
    133 
    134 BENCHMARK_IMPL(async4) {
    135   return test_async(4);
    136 }
    137 
    138 
    139 BENCHMARK_IMPL(async8) {
    140   return test_async(8);
    141 }
    142