Blame test/benchmark-udp-pummel.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
#include <stdio.h>
Packit b5b901
#include <stdlib.h>
Packit b5b901
#include <string.h>
Packit b5b901
Packit b5b901
#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN"
Packit b5b901
Packit b5b901
#define TEST_DURATION 5000 /* ms */
Packit b5b901
Packit b5b901
#define BASE_PORT 12345
Packit b5b901
Packit b5b901
struct sender_state {
Packit b5b901
  struct sockaddr_in addr;
Packit b5b901
  uv_udp_send_t send_req;
Packit b5b901
  uv_udp_t udp_handle;
Packit b5b901
};
Packit b5b901
Packit b5b901
struct receiver_state {
Packit b5b901
  struct sockaddr_in addr;
Packit b5b901
  uv_udp_t udp_handle;
Packit b5b901
};
Packit b5b901
Packit b5b901
/* not used in timed mode */
Packit b5b901
static unsigned int packet_counter = (unsigned int) 1e6;
Packit b5b901
Packit b5b901
static int n_senders_;
Packit b5b901
static int n_receivers_;
Packit b5b901
static uv_buf_t bufs[5];
Packit b5b901
static struct sender_state senders[1024];
Packit b5b901
static struct receiver_state receivers[1024];
Packit b5b901
Packit b5b901
static unsigned int send_cb_called;
Packit b5b901
static unsigned int recv_cb_called;
Packit b5b901
static unsigned int close_cb_called;
Packit b5b901
static int timed;
Packit b5b901
static int exiting;
Packit b5b901
Packit b5b901
Packit b5b901
static void alloc_cb(uv_handle_t* handle,
Packit b5b901
                     size_t suggested_size,
Packit b5b901
                     uv_buf_t* buf) {
Packit b5b901
  static char slab[65536];
Packit b5b901
  ASSERT(suggested_size <= sizeof(slab));
Packit b5b901
  buf->base = slab;
Packit b5b901
  buf->len = sizeof(slab);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void send_cb(uv_udp_send_t* req, int status) {
Packit b5b901
  struct sender_state* s;
Packit b5b901
Packit b5b901
  ASSERT(req != NULL);
Packit b5b901
Packit b5b901
  if (status != 0) {
Packit b5b901
    ASSERT(status == UV_ECANCELED);
Packit b5b901
    return;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  if (exiting)
Packit b5b901
    return;
Packit b5b901
Packit b5b901
  s = container_of(req, struct sender_state, send_req);
Packit b5b901
  ASSERT(req->handle == &s->udp_handle);
Packit b5b901
Packit b5b901
  if (timed)
Packit b5b901
    goto send;
Packit b5b901
Packit b5b901
  if (packet_counter == 0) {
Packit b5b901
    uv_close((uv_handle_t*)&s->udp_handle, NULL);
Packit b5b901
    return;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  packet_counter--;
Packit b5b901
Packit b5b901
send:
Packit b5b901
  ASSERT(0 == uv_udp_send(&s->send_req,
Packit b5b901
                          &s->udp_handle,
Packit b5b901
                          bufs,
Packit b5b901
                          ARRAY_SIZE(bufs),
Packit b5b901
                          (const struct sockaddr*) &s->addr,
Packit b5b901
                          send_cb));
Packit b5b901
  send_cb_called++;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void recv_cb(uv_udp_t* handle,
Packit b5b901
                    ssize_t nread,
Packit b5b901
                    const uv_buf_t* buf,
Packit b5b901
                    const struct sockaddr* addr,
Packit b5b901
                    unsigned flags) {
Packit b5b901
  if (nread == 0)
Packit b5b901
    return;
Packit b5b901
Packit b5b901
  if (nread < 0) {
Packit b5b901
    ASSERT(nread == UV_ECANCELED);
Packit b5b901
    return;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  ASSERT(addr->sa_family == AF_INET);
Packit b5b901
  ASSERT(!memcmp(buf->base, EXPECTED, nread));
Packit b5b901
Packit b5b901
  recv_cb_called++;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void close_cb(uv_handle_t* handle) {
Packit b5b901
  ASSERT(handle != NULL);
Packit b5b901
  close_cb_called++;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static void timeout_cb(uv_timer_t* timer) {
Packit b5b901
  int i;
Packit b5b901
Packit b5b901
  exiting = 1;
Packit b5b901
Packit b5b901
  for (i = 0; i < n_senders_; i++)
Packit b5b901
    uv_close((uv_handle_t*)&senders[i].udp_handle, close_cb);
Packit b5b901
Packit b5b901
  for (i = 0; i < n_receivers_; i++)
Packit b5b901
    uv_close((uv_handle_t*)&receivers[i].udp_handle, close_cb);
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
static int pummel(unsigned int n_senders,
Packit b5b901
                  unsigned int n_receivers,
Packit b5b901
                  unsigned long timeout) {
Packit b5b901
  uv_timer_t timer_handle;
Packit b5b901
  uint64_t duration;
Packit b5b901
  uv_loop_t* loop;
Packit b5b901
  unsigned int i;
Packit b5b901
Packit b5b901
  ASSERT(n_senders <= ARRAY_SIZE(senders));
Packit b5b901
  ASSERT(n_receivers <= ARRAY_SIZE(receivers));
Packit b5b901
Packit b5b901
  loop = uv_default_loop();
Packit b5b901
Packit b5b901
  n_senders_ = n_senders;
Packit b5b901
  n_receivers_ = n_receivers;
Packit b5b901
Packit b5b901
  if (timeout) {
Packit b5b901
    ASSERT(0 == uv_timer_init(loop, &timer_handle));
Packit b5b901
    ASSERT(0 == uv_timer_start(&timer_handle, timeout_cb, timeout, 0));
Packit b5b901
    /* Timer should not keep loop alive. */
Packit b5b901
    uv_unref((uv_handle_t*)&timer_handle);
Packit b5b901
    timed = 1;
Packit b5b901
  }
Packit b5b901
Packit b5b901
  for (i = 0; i < n_receivers; i++) {
Packit b5b901
    struct receiver_state* s = receivers + i;
Packit b5b901
    struct sockaddr_in addr;
Packit b5b901
    ASSERT(0 == uv_ip4_addr("0.0.0.0", BASE_PORT + i, &addr));
Packit b5b901
    ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
Packit b5b901
    ASSERT(0 == uv_udp_bind(&s->udp_handle, (const struct sockaddr*) &addr, 0));
Packit b5b901
    ASSERT(0 == uv_udp_recv_start(&s->udp_handle, alloc_cb, recv_cb));
Packit b5b901
    uv_unref((uv_handle_t*)&s->udp_handle);
Packit b5b901
  }
Packit b5b901
Packit b5b901
  bufs[0] = uv_buf_init(EXPECTED + 0,  10);
Packit b5b901
  bufs[1] = uv_buf_init(EXPECTED + 10, 10);
Packit b5b901
  bufs[2] = uv_buf_init(EXPECTED + 20, 10);
Packit b5b901
  bufs[3] = uv_buf_init(EXPECTED + 30, 10);
Packit b5b901
  bufs[4] = uv_buf_init(EXPECTED + 40, 5);
Packit b5b901
Packit b5b901
  for (i = 0; i < n_senders; i++) {
Packit b5b901
    struct sender_state* s = senders + i;
Packit b5b901
    ASSERT(0 == uv_ip4_addr("127.0.0.1",
Packit b5b901
                            BASE_PORT + (i % n_receivers),
Packit b5b901
                            &s->addr));
Packit b5b901
    ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
Packit b5b901
    ASSERT(0 == uv_udp_send(&s->send_req,
Packit b5b901
                            &s->udp_handle,
Packit b5b901
                            bufs,
Packit b5b901
                            ARRAY_SIZE(bufs),
Packit b5b901
                            (const struct sockaddr*) &s->addr,
Packit b5b901
                            send_cb));
Packit b5b901
  }
Packit b5b901
Packit b5b901
  duration = uv_hrtime();
Packit b5b901
  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit b5b901
  duration = uv_hrtime() - duration;
Packit b5b901
  /* convert from nanoseconds to milliseconds */
Packit b5b901
  duration = duration / (uint64_t) 1e6;
Packit b5b901
Packit b5b901
  printf("udp_pummel_%dv%d: %.0f/s received, %.0f/s sent. "
Packit b5b901
         "%u received, %u sent in %.1f seconds.\n",
Packit b5b901
         n_receivers,
Packit b5b901
         n_senders,
Packit b5b901
         recv_cb_called / (duration / 1000.0),
Packit b5b901
         send_cb_called / (duration / 1000.0),
Packit b5b901
         recv_cb_called,
Packit b5b901
         send_cb_called,
Packit b5b901
         duration / 1000.0);
Packit b5b901
Packit b5b901
  MAKE_VALGRIND_HAPPY();
Packit b5b901
  return 0;
Packit b5b901
}
Packit b5b901
Packit b5b901
Packit b5b901
#define X(a, b)                                                               \
Packit b5b901
  BENCHMARK_IMPL(udp_pummel_##a##v##b) {                                      \
Packit b5b901
    return pummel(a, b, 0);                                                   \
Packit b5b901
  }                                                                           \
Packit b5b901
  BENCHMARK_IMPL(udp_timed_pummel_##a##v##b) {                                \
Packit b5b901
    return pummel(a, b, TEST_DURATION);                                       \
Packit b5b901
  }
Packit b5b901
Packit b5b901
X(1, 1)
Packit b5b901
X(1, 10)
Packit b5b901
X(1, 100)
Packit b5b901
X(1, 1000)
Packit b5b901
X(10, 10)
Packit b5b901
X(10, 100)
Packit b5b901
X(10, 1000)
Packit b5b901
X(100, 10)
Packit b5b901
X(100, 100)
Packit b5b901
X(100, 1000)
Packit b5b901
X(1000, 1000)
Packit b5b901
Packit b5b901
#undef X