Blame test/benchmark-multi-accept.c

Packit b5b901
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit b5b901
 *
Packit b5b901
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit b5b901
 * of this software and associated documentation files (the "Software"), to
Packit b5b901
 * deal in the Software without restriction, including without limitation the
Packit b5b901
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit b5b901
 * sell copies of the Software, and to permit persons to whom the Software is
Packit b5b901
 * furnished to do so, subject to the following conditions:
Packit b5b901
 *
Packit b5b901
 * The above copyright notice and this permission notice shall be included in
Packit b5b901
 * all copies or substantial portions of the Software.
Packit b5b901
 *
Packit b5b901
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit b5b901
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit b5b901
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit b5b901
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit b5b901
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit b5b901
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit b5b901
 * IN THE SOFTWARE.
Packit b5b901
 */
Packit b5b901
Packit b5b901
#include "task.h"
Packit b5b901
#include "uv.h"
Packit b5b901
Packit b5b901
#define IPC_PIPE_NAME TEST_PIPENAME
Packit b5b901
#define NUM_CONNECTS  (250 * 1000)
Packit b5b901
Packit b5b901
union stream_handle {
Packit b5b901
  uv_pipe_t pipe;
Packit b5b901
  uv_tcp_t tcp;
Packit b5b901
};
Packit b5b901
Packit b5b901
/* Use as (uv_stream_t *) &handle_storage -- it's kind of clunky but it
Packit b5b901
 * avoids aliasing warnings.
Packit b5b901
 */
Packit b5b901
typedef unsigned char handle_storage_t[sizeof(union stream_handle)];
Packit b5b901
Packit b5b901
/* Used for passing around the listen handle, not part of the benchmark proper.
Packit b5b901
 * We have an overabundance of server types here. It works like this:
Packit b5b901
 *
Packit b5b901
 *  1. The main thread starts an IPC pipe server.
Packit b5b901
 *  2. The worker threads connect to the IPC server and obtain a listen handle.
Packit b5b901
 *  3. The worker threads start accepting requests on the listen handle.
Packit b5b901
 *  4. The main thread starts connecting repeatedly.
Packit b5b901
 *
Packit b5b901
 * Step #4 should perhaps be farmed out over several threads.
Packit b5b901
 */
Packit b5b901
struct ipc_server_ctx {
Packit b5b901
  handle_storage_t server_handle;
Packit b5b901
  unsigned int num_connects;
Packit b5b901
  uv_pipe_t ipc_pipe;
Packit b5b901
};
Packit b5b901
Packit b5b901
struct ipc_peer_ctx {
Packit b5b901
  handle_storage_t peer_handle;
Packit b5b901
  uv_write_t write_req;
Packit b5b901
};
Packit b5b901
Packit b5b901
struct ipc_client_ctx {
Packit b5b901
  uv_connect_t connect_req;
Packit b5b901
  uv_stream_t* server_handle;
Packit b5b901
  uv_pipe_t ipc_pipe;
Packit b5b901
  char scratch[16];
Packit b5b901
};
Packit b5b901
Packit b5b901
/* Used in the actual benchmark. */
Packit b5b901
struct server_ctx {
Packit b5b901
  handle_storage_t server_handle;
Packit b5b901
  unsigned int num_connects;
Packit b5b901
  uv_async_t async_handle;
Packit b5b901
  uv_thread_t thread_id;
Packit b5b901
  uv_sem_t semaphore;
Packit b5b901
};
Packit b5b901
Packit b5b901
struct client_ctx {
Packit b5b901
  handle_storage_t client_handle;
Packit b5b901
  unsigned int num_connects;
Packit b5b901
  uv_connect_t connect_req;
Packit b5b901
  uv_idle_t idle_handle;
Packit b5b901
};
Packit b5b901
Packit b5b901
static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status);
Packit b5b901
static void ipc_write_cb(uv_write_t* req, int status);
Packit b5b901
static void ipc_close_cb(uv_handle_t* handle);
Packit b5b901
static void ipc_connect_cb(uv_connect_t* req, int status);
Packit b5b901
static void ipc_read_cb(uv_stream_t* handle,
Packit b5b901
                        ssize_t nread,
Packit b5b901
                        const uv_buf_t* buf);
Packit b5b901
static void ipc_alloc_cb(uv_handle_t* handle,
Packit b5b901
                         size_t suggested_size,
Packit b5b901
                         uv_buf_t* buf);
Packit b5b901
Packit b5b901
static void sv_async_cb(uv_async_t* handle);
Packit b5b901
static void sv_connection_cb(uv_stream_t* server_handle, int status);
Packit b5b901
static void sv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf);
Packit b5b901
static void sv_alloc_cb(uv_handle_t* handle,
Packit b5b901
                        size_t suggested_size,
Packit b5b901
                        uv_buf_t* buf);
Packit b5b901
Packit b5b901
static void cl_connect_cb(uv_connect_t* req, int status);
Packit b5b901
static void cl_idle_cb(uv_idle_t* handle);
Packit b5b901
static void cl_close_cb(uv_handle_t* handle);
Packit b5b901
Packit b5b901
static struct sockaddr_in listen_addr;
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_connection_cb(uv_stream_t* ipc_pipe, int status) {
Packit b5b901
  struct ipc_server_ctx* sc;
Packit b5b901
  struct ipc_peer_ctx* pc;
Packit b5b901
  uv_loop_t* loop;
Packit b5b901
  uv_buf_t buf;
Packit b5b901
Packit b5b901
  loop = ipc_pipe->loop;
Packit b5b901
  buf = uv_buf_init("PING", 4);
Packit b5b901
  sc = container_of(ipc_pipe, struct ipc_server_ctx, ipc_pipe);
Packit b5b901
  pc = calloc(1, sizeof(*pc));
Packit b5b901
  ASSERT(pc != NULL);
Packit b5b901
Packit b5b901
  if (ipc_pipe->type == UV_TCP)
Packit b5b901
    ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &pc->peer_handle));
Packit b5b901
  else if (ipc_pipe->type == UV_NAMED_PIPE)
Packit b5b901
    ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) &pc->peer_handle, 1));
Packit b5b901
  else
Packit b5b901
    ASSERT(0);
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_accept(ipc_pipe, (uv_stream_t*) &pc->peer_handle));
Packit b5b901
  ASSERT(0 == uv_write2(&pc->write_req,
Packit b5b901
                        (uv_stream_t*) &pc->peer_handle,
Packit b5b901
                        &buf,
Packit b5b901
                        1,
Packit b5b901
                        (uv_stream_t*) &sc->server_handle,
Packit b5b901
                        ipc_write_cb));
Packit b5b901
Packit b5b901
  if (--sc->num_connects == 0)
Packit b5b901
    uv_close((uv_handle_t*) ipc_pipe, NULL);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_write_cb(uv_write_t* req, int status) {
Packit b5b901
  struct ipc_peer_ctx* ctx;
Packit b5b901
  ctx = container_of(req, struct ipc_peer_ctx, write_req);
Packit b5b901
  uv_close((uv_handle_t*) &ctx->peer_handle, ipc_close_cb);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_close_cb(uv_handle_t* handle) {
Packit b5b901
  struct ipc_peer_ctx* ctx;
Packit b5b901
  ctx = container_of(handle, struct ipc_peer_ctx, peer_handle);
Packit b5b901
  free(ctx);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_connect_cb(uv_connect_t* req, int status) {
Packit b5b901
  struct ipc_client_ctx* ctx;
Packit b5b901
  ctx = container_of(req, struct ipc_client_ctx, connect_req);
Packit b5b901
  ASSERT(0 == status);
Packit b5b901
  ASSERT(0 == uv_read_start((uv_stream_t*) &ctx->ipc_pipe,
Packit b5b901
                            ipc_alloc_cb,
Packit b5b901
                            ipc_read_cb));
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_alloc_cb(uv_handle_t* handle,
Packit b5b901
                         size_t suggested_size,
Packit b5b901
                         uv_buf_t* buf) {
Packit b5b901
  struct ipc_client_ctx* ctx;
Packit b5b901
  ctx = container_of(handle, struct ipc_client_ctx, ipc_pipe);
Packit b5b901
  buf->base = ctx->scratch;
Packit b5b901
  buf->len = sizeof(ctx->scratch);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void ipc_read_cb(uv_stream_t* handle,
Packit b5b901
                        ssize_t nread,
Packit b5b901
                        const uv_buf_t* buf) {
Packit b5b901
  struct ipc_client_ctx* ctx;
Packit b5b901
  uv_loop_t* loop;
Packit b5b901
  uv_handle_type type;
Packit b5b901
  uv_pipe_t* ipc_pipe;
Packit b5b901
Packit b5b901
  ipc_pipe = (uv_pipe_t*) handle;
Packit b5b901
  ctx = container_of(ipc_pipe, struct ipc_client_ctx, ipc_pipe);
Packit b5b901
  loop = ipc_pipe->loop;
Packit b5b901
Packit b5b901
  ASSERT(1 == uv_pipe_pending_count(ipc_pipe));
Packit b5b901
  type = uv_pipe_pending_type(ipc_pipe);
Packit b5b901
  if (type == UV_TCP)
Packit b5b901
    ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) ctx->server_handle));
Packit b5b901
  else if (type == UV_NAMED_PIPE)
Packit b5b901
    ASSERT(0 == uv_pipe_init(loop, (uv_pipe_t*) ctx->server_handle, 0));
Packit b5b901
  else
Packit b5b901
    ASSERT(0);
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_accept(handle, ctx->server_handle));
Packit b5b901
  uv_close((uv_handle_t*) &ctx->ipc_pipe, NULL);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
/* Set up an IPC pipe server that hands out listen sockets to the worker
Packit b5b901
 * threads. It's kind of cumbersome for such a simple operation, maybe we
Packit b5b901
 * should revive uv_import() and uv_export().
Packit b5b901
 */
Packit b5b901
static void send_listen_handles(uv_handle_type type,
Packit b5b901
                                unsigned int num_servers,
Packit b5b901
                                struct server_ctx* servers) {
Packit b5b901
  struct ipc_server_ctx ctx;
Packit b5b901
  uv_loop_t* loop;
Packit b5b901
  unsigned int i;
Packit b5b901
Packit b5b901
  loop = uv_default_loop();
Packit b5b901
  ctx.num_connects = num_servers;
Packit b5b901
Packit b5b901
  if (type == UV_TCP) {
Packit b5b901
    ASSERT(0 == uv_tcp_init(loop, (uv_tcp_t*) &ctx.server_handle));
Packit b5b901
    ASSERT(0 == uv_tcp_bind((uv_tcp_t*) &ctx.server_handle,
Packit b5b901
                            (const struct sockaddr*) &listen_addr,
Packit b5b901
                            0));
Packit b5b901
  }
Packit b5b901
  else
Packit b5b901
    ASSERT(0);
Packit Service e08953
  /* We need to initialize this pipe with ipc=0 - this is not a uv_pipe we'll
Packit Service e08953
   * be sending handles over, it's just for listening for new connections.
Packit Service e08953
   * If we accept a connection then the connected pipe must be initialized
Packit Service e08953
   * with ipc=1.
Packit Service e08953
   */
Packit Service e08953
  ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 0));
Packit b5b901
  ASSERT(0 == uv_pipe_bind(&ctx.ipc_pipe, IPC_PIPE_NAME));
Packit b5b901
  ASSERT(0 == uv_listen((uv_stream_t*) &ctx.ipc_pipe, 128, ipc_connection_cb));
Packit b5b901
Packit b5b901
  for (i = 0; i < num_servers; i++)
Packit b5b901
    uv_sem_post(&servers[i].semaphore);
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit b5b901
  uv_close((uv_handle_t*) &ctx.server_handle, NULL);
Packit b5b901
  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit b5b901
Packit b5b901
  for (i = 0; i < num_servers; i++)
Packit b5b901
    uv_sem_wait(&servers[i].semaphore);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void get_listen_handle(uv_loop_t* loop, uv_stream_t* server_handle) {
Packit b5b901
  struct ipc_client_ctx ctx;
Packit b5b901
Packit b5b901
  ctx.server_handle = server_handle;
Packit b5b901
  ctx.server_handle->data = "server handle";
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_pipe_init(loop, &ctx.ipc_pipe, 1));
Packit b5b901
  uv_pipe_connect(&ctx.connect_req,
Packit b5b901
                  &ctx.ipc_pipe,
Packit b5b901
                  IPC_PIPE_NAME,
Packit b5b901
                  ipc_connect_cb);
Packit b5b901
  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void server_cb(void *arg) {
Packit b5b901
  struct server_ctx *ctx;
Packit b5b901
  uv_loop_t loop;
Packit b5b901
Packit b5b901
  ctx = arg;
Packit b5b901
  ASSERT(0 == uv_loop_init(&loop);;
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_async_init(&loop, &ctx->async_handle, sv_async_cb));
Packit b5b901
  uv_unref((uv_handle_t*) &ctx->async_handle);
Packit b5b901
Packit b5b901
  /* Wait until the main thread is ready. */
Packit b5b901
  uv_sem_wait(&ctx->semaphore);
Packit b5b901
  get_listen_handle(&loop, (uv_stream_t*) &ctx->server_handle);
Packit b5b901
  uv_sem_post(&ctx->semaphore);
Packit b5b901
Packit b5b901
  /* Now start the actual benchmark. */
Packit b5b901
  ASSERT(0 == uv_listen((uv_stream_t*) &ctx->server_handle,
Packit b5b901
                        128,
Packit b5b901
                        sv_connection_cb));
Packit b5b901
  ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
Packit b5b901
Packit b5b901
  uv_loop_close(&loop);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void sv_async_cb(uv_async_t* handle) {
Packit b5b901
  struct server_ctx* ctx;
Packit b5b901
  ctx = container_of(handle, struct server_ctx, async_handle);
Packit b5b901
  uv_close((uv_handle_t*) &ctx->server_handle, NULL);
Packit b5b901
  uv_close((uv_handle_t*) &ctx->async_handle, NULL);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void sv_connection_cb(uv_stream_t* server_handle, int status) {
Packit b5b901
  handle_storage_t* storage;
Packit b5b901
  struct server_ctx* ctx;
Packit b5b901
Packit b5b901
  ctx = container_of(server_handle, struct server_ctx, server_handle);
Packit b5b901
  ASSERT(status == 0);
Packit b5b901
Packit b5b901
  storage = malloc(sizeof(*storage));
Packit b5b901
  ASSERT(storage != NULL);
Packit b5b901
Packit b5b901
  if (server_handle->type == UV_TCP)
Packit b5b901
    ASSERT(0 == uv_tcp_init(server_handle->loop, (uv_tcp_t*) storage));
Packit b5b901
  else if (server_handle->type == UV_NAMED_PIPE)
Packit b5b901
    ASSERT(0 == uv_pipe_init(server_handle->loop, (uv_pipe_t*) storage, 0));
Packit b5b901
  else
Packit b5b901
    ASSERT(0);
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_accept(server_handle, (uv_stream_t*) storage));
Packit b5b901
  ASSERT(0 == uv_read_start((uv_stream_t*) storage, sv_alloc_cb, sv_read_cb));
Packit b5b901
  ctx->num_connects++;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void sv_alloc_cb(uv_handle_t* handle,
Packit b5b901
                        size_t suggested_size,
Packit b5b901
                        uv_buf_t* buf) {
Packit b5b901
  static char slab[32];
Packit b5b901
  buf->base = slab;
Packit b5b901
  buf->len = sizeof(slab);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void sv_read_cb(uv_stream_t* handle,
Packit b5b901
                       ssize_t nread,
Packit b5b901
                       const uv_buf_t* buf) {
Packit b5b901
  ASSERT(nread == UV_EOF);
Packit b5b901
  uv_close((uv_handle_t*) handle, (uv_close_cb) free);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void cl_connect_cb(uv_connect_t* req, int status) {
Packit b5b901
  struct client_ctx* ctx = container_of(req, struct client_ctx, connect_req);
Packit b5b901
  uv_idle_start(&ctx->idle_handle, cl_idle_cb);
Packit b5b901
  ASSERT(0 == status);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void cl_idle_cb(uv_idle_t* handle) {
Packit b5b901
  struct client_ctx* ctx = container_of(handle, struct client_ctx, idle_handle);
Packit b5b901
  uv_close((uv_handle_t*) &ctx->client_handle, cl_close_cb);
Packit b5b901
  uv_idle_stop(&ctx->idle_handle);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void cl_close_cb(uv_handle_t* handle) {
Packit b5b901
  struct client_ctx* ctx;
Packit b5b901
Packit b5b901
  ctx = container_of(handle, struct client_ctx, client_handle);
Packit b5b901
Packit b5b901
  if (--ctx->num_connects == 0) {
Packit b5b901
    uv_close((uv_handle_t*) &ctx->idle_handle, NULL);
Packit b5b901
    return;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_tcp_init(handle->loop, (uv_tcp_t*) &ctx->client_handle));
Packit b5b901
  ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
Packit b5b901
                             (uv_tcp_t*) &ctx->client_handle,
Packit b5b901
                             (const struct sockaddr*) &listen_addr,
Packit b5b901
                             cl_connect_cb));
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static int test_tcp(unsigned int num_servers, unsigned int num_clients) {
Packit b5b901
  struct server_ctx* servers;
Packit b5b901
  struct client_ctx* clients;
Packit b5b901
  uv_loop_t* loop;
Packit b5b901
  uv_tcp_t* handle;
Packit b5b901
  unsigned int i;
Packit b5b901
  double time;
Packit b5b901
Packit b5b901
  ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &listen_addr));
Packit b5b901
  loop = uv_default_loop();
Packit b5b901
Packit b5b901
  servers = calloc(num_servers, sizeof(servers[0]));
Packit b5b901
  clients = calloc(num_clients, sizeof(clients[0]));
Packit b5b901
  ASSERT(servers != NULL);
Packit b5b901
  ASSERT(clients != NULL);
Packit b5b901
Packit b5b901
  /* We're making the assumption here that from the perspective of the
Packit b5b901
   * OS scheduler, threads are functionally equivalent to and interchangeable
Packit b5b901
   * with full-blown processes.
Packit b5b901
   */
Packit b5b901
  for (i = 0; i < num_servers; i++) {
Packit b5b901
    struct server_ctx* ctx = servers + i;
Packit b5b901
    ASSERT(0 == uv_sem_init(&ctx->semaphore, 0));
Packit b5b901
    ASSERT(0 == uv_thread_create(&ctx->thread_id, server_cb, ctx));
Packit b5b901
  }
Packit b5b901
Packit b5b901
  send_listen_handles(UV_TCP, num_servers, servers);
Packit b5b901
Packit b5b901
  for (i = 0; i < num_clients; i++) {
Packit b5b901
    struct client_ctx* ctx = clients + i;
Packit b5b901
    ctx->num_connects = NUM_CONNECTS / num_clients;
Packit b5b901
    handle = (uv_tcp_t*) &ctx->client_handle;
Packit b5b901
    handle->data = "client handle";
Packit b5b901
    ASSERT(0 == uv_tcp_init(loop, handle));
Packit b5b901
    ASSERT(0 == uv_tcp_connect(&ctx->connect_req,
Packit b5b901
                               handle,
Packit b5b901
                               (const struct sockaddr*) &listen_addr,
Packit b5b901
                               cl_connect_cb));
Packit b5b901
    ASSERT(0 == uv_idle_init(loop, &ctx->idle_handle));
Packit b5b901
  }
Packit b5b901
Packit b5b901
  {
Packit b5b901
    uint64_t t = uv_hrtime();
Packit b5b901
    ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit b5b901
    t = uv_hrtime() - t;
Packit b5b901
    time = t / 1e9;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  for (i = 0; i < num_servers; i++) {
Packit b5b901
    struct server_ctx* ctx = servers + i;
Packit b5b901
    uv_async_send(&ctx->async_handle);
Packit b5b901
    ASSERT(0 == uv_thread_join(&ctx->thread_id));
Packit b5b901
    uv_sem_destroy(&ctx->semaphore);
Packit b5b901
  }
Packit b5b901
Packit b5b901
  printf("accept%u: %.0f accepts/sec (%u total)\n",
Packit b5b901
         num_servers,
Packit b5b901
         NUM_CONNECTS / time,
Packit b5b901
         NUM_CONNECTS);
Packit b5b901
Packit b5b901
  for (i = 0; i < num_servers; i++) {
Packit b5b901
    struct server_ctx* ctx = servers + i;
Packit b5b901
    printf("  thread #%u: %.0f accepts/sec (%u total, %.1f%%)\n",
Packit b5b901
           i,
Packit b5b901
           ctx->num_connects / time,
Packit b5b901
           ctx->num_connects,
Packit b5b901
           ctx->num_connects * 100.0 / NUM_CONNECTS);
Packit b5b901
  }
Packit b5b901
Packit b5b901
  free(clients);
Packit b5b901
  free(servers);
Packit b5b901
Packit b5b901
  MAKE_VALGRIND_HAPPY();
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
BENCHMARK_IMPL(tcp_multi_accept2) {
Packit b5b901
  return test_tcp(2, 40);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
BENCHMARK_IMPL(tcp_multi_accept4) {
Packit b5b901
  return test_tcp(4, 40);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
BENCHMARK_IMPL(tcp_multi_accept8) {
Packit b5b901
  return test_tcp(8, 40);
Packit b5b901
}