xref: /third_party/libuv/test/benchmark-async.c (revision e66f31c5)
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
30struct 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
43static void worker_async_cb(uv_async_t* handle) {
44  struct ctx* ctx = container_of(handle, struct ctx, worker_async);
45
46  ASSERT_OK(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
55static void main_async_cb(uv_async_t* handle) {
56  struct ctx* ctx = container_of(handle, struct ctx, main_async);
57
58  ASSERT_OK(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
67static void worker(void* arg) {
68  struct ctx* ctx = arg;
69  ASSERT_OK(uv_async_send(&ctx->main_async));
70  ASSERT_OK(uv_run(&ctx->loop, UV_RUN_DEFAULT));
71  uv_loop_close(&ctx->loop);
72}
73
74
75static int test_async(int nthreads) {
76  char fmtbuf[32];
77  struct ctx* threads;
78  struct ctx* ctx;
79  uint64_t time;
80  int i;
81
82  threads = calloc(nthreads, sizeof(threads[0]));
83  ASSERT_NOT_NULL(threads);
84
85  for (i = 0; i < nthreads; i++) {
86    ctx = threads + i;
87    ctx->nthreads = nthreads;
88    ASSERT_OK(uv_loop_init(&ctx->loop));
89    ASSERT_OK(uv_async_init(&ctx->loop, &ctx->worker_async, worker_async_cb));
90    ASSERT_OK(uv_async_init(uv_default_loop(),
91                            &ctx->main_async,
92                            main_async_cb));
93    ASSERT_OK(uv_thread_create(&ctx->thread, worker, ctx));
94  }
95
96  time = uv_hrtime();
97
98  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
99
100  for (i = 0; i < nthreads; i++)
101    ASSERT_OK(uv_thread_join(&threads[i].thread));
102
103  time = uv_hrtime() - time;
104
105  for (i = 0; i < nthreads; i++) {
106    ctx = threads + i;
107    ASSERT_EQ(ctx->worker_sent, NUM_PINGS);
108    ASSERT_EQ(ctx->worker_seen, NUM_PINGS);
109    ASSERT_EQ(ctx->main_sent, (unsigned int) NUM_PINGS);
110    ASSERT_EQ(ctx->main_seen, (unsigned int) NUM_PINGS);
111  }
112
113  printf("async%d: %.2f sec (%s/sec)\n",
114         nthreads,
115         time / 1e9,
116         fmt(&fmtbuf, NUM_PINGS / (time / 1e9)));
117
118  free(threads);
119
120  MAKE_VALGRIND_HAPPY(uv_default_loop());
121  return 0;
122}
123
124
125BENCHMARK_IMPL(async1) {
126  return test_async(1);
127}
128
129
130BENCHMARK_IMPL(async2) {
131  return test_async(2);
132}
133
134
135BENCHMARK_IMPL(async4) {
136  return test_async(4);
137}
138
139
140BENCHMARK_IMPL(async8) {
141  return test_async(8);
142}
143