Blame test/benchmark-udp-pummel.c

Packit Service 7c31a4
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service 7c31a4
 * of this software and associated documentation files (the "Software"), to
Packit Service 7c31a4
 * deal in the Software without restriction, including without limitation the
Packit Service 7c31a4
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service 7c31a4
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service 7c31a4
 * furnished to do so, subject to the following conditions:
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * The above copyright notice and this permission notice shall be included in
Packit Service 7c31a4
 * all copies or substantial portions of the Software.
Packit Service 7c31a4
 *
Packit Service 7c31a4
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 7c31a4
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 7c31a4
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service 7c31a4
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service 7c31a4
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service 7c31a4
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service 7c31a4
 * IN THE SOFTWARE.
Packit Service 7c31a4
 */
Packit Service 7c31a4
Packit Service 7c31a4
#include "task.h"
Packit Service 7c31a4
#include "uv.h"
Packit Service 7c31a4
Packit Service 7c31a4
#include <stdio.h>
Packit Service 7c31a4
#include <stdlib.h>
Packit Service 7c31a4
#include <string.h>
Packit Service 7c31a4
Packit Service 7c31a4
#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN"
Packit Service 7c31a4
Packit Service 7c31a4
#define TEST_DURATION 5000 /* ms */
Packit Service 7c31a4
Packit Service 7c31a4
#define BASE_PORT 12345
Packit Service 7c31a4
Packit Service 7c31a4
struct sender_state {
Packit Service 7c31a4
  struct sockaddr_in addr;
Packit Service 7c31a4
  uv_udp_send_t send_req;
Packit Service 7c31a4
  uv_udp_t udp_handle;
Packit Service 7c31a4
};
Packit Service 7c31a4
Packit Service 7c31a4
struct receiver_state {
Packit Service 7c31a4
  struct sockaddr_in addr;
Packit Service 7c31a4
  uv_udp_t udp_handle;
Packit Service 7c31a4
};
Packit Service 7c31a4
Packit Service 7c31a4
/* not used in timed mode */
Packit Service 7c31a4
static unsigned int packet_counter = (unsigned int) 1e6;
Packit Service 7c31a4
Packit Service 7c31a4
static int n_senders_;
Packit Service 7c31a4
static int n_receivers_;
Packit Service 7c31a4
static uv_buf_t bufs[5];
Packit Service 7c31a4
static struct sender_state senders[1024];
Packit Service 7c31a4
static struct receiver_state receivers[1024];
Packit Service 7c31a4
Packit Service 7c31a4
static unsigned int send_cb_called;
Packit Service 7c31a4
static unsigned int recv_cb_called;
Packit Service 7c31a4
static unsigned int close_cb_called;
Packit Service 7c31a4
static int timed;
Packit Service 7c31a4
static int exiting;
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void alloc_cb(uv_handle_t* handle,
Packit Service 7c31a4
                     size_t suggested_size,
Packit Service 7c31a4
                     uv_buf_t* buf) {
Packit Service 7c31a4
  static char slab[65536];
Packit Service 7c31a4
  ASSERT(suggested_size <= sizeof(slab));
Packit Service 7c31a4
  buf->base = slab;
Packit Service 7c31a4
  buf->len = sizeof(slab);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void send_cb(uv_udp_send_t* req, int status) {
Packit Service 7c31a4
  struct sender_state* s;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(req != NULL);
Packit Service 7c31a4
Packit Service 7c31a4
  if (status != 0) {
Packit Service 7c31a4
    ASSERT(status == UV_ECANCELED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  if (exiting)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  s = container_of(req, struct sender_state, send_req);
Packit Service 7c31a4
  ASSERT(req->handle == &s->udp_handle);
Packit Service 7c31a4
Packit Service 7c31a4
  if (timed)
Packit Service 7c31a4
    goto send;
Packit Service 7c31a4
Packit Service 7c31a4
  if (packet_counter == 0) {
Packit Service 7c31a4
    uv_close((uv_handle_t*)&s->udp_handle, NULL);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  packet_counter--;
Packit Service 7c31a4
Packit Service 7c31a4
send:
Packit Service 7c31a4
  ASSERT(0 == uv_udp_send(&s->send_req,
Packit Service 7c31a4
                          &s->udp_handle,
Packit Service 7c31a4
                          bufs,
Packit Service 7c31a4
                          ARRAY_SIZE(bufs),
Packit Service 7c31a4
                          (const struct sockaddr*) &s->addr,
Packit Service 7c31a4
                          send_cb));
Packit Service 7c31a4
  send_cb_called++;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void recv_cb(uv_udp_t* handle,
Packit Service 7c31a4
                    ssize_t nread,
Packit Service 7c31a4
                    const uv_buf_t* buf,
Packit Service 7c31a4
                    const struct sockaddr* addr,
Packit Service 7c31a4
                    unsigned flags) {
Packit Service 7c31a4
  if (nread == 0)
Packit Service 7c31a4
    return;
Packit Service 7c31a4
Packit Service 7c31a4
  if (nread < 0) {
Packit Service 7c31a4
    ASSERT(nread == UV_ECANCELED);
Packit Service 7c31a4
    return;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(addr->sa_family == AF_INET);
Packit Service 7c31a4
  ASSERT(!memcmp(buf->base, EXPECTED, nread));
Packit Service 7c31a4
Packit Service 7c31a4
  recv_cb_called++;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void close_cb(uv_handle_t* handle) {
Packit Service 7c31a4
  ASSERT(handle != NULL);
Packit Service 7c31a4
  close_cb_called++;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static void timeout_cb(uv_timer_t* timer) {
Packit Service 7c31a4
  int i;
Packit Service 7c31a4
Packit Service 7c31a4
  exiting = 1;
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < n_senders_; i++)
Packit Service 7c31a4
    uv_close((uv_handle_t*)&senders[i].udp_handle, close_cb);
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < n_receivers_; i++)
Packit Service 7c31a4
    uv_close((uv_handle_t*)&receivers[i].udp_handle, close_cb);
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
static int pummel(unsigned int n_senders,
Packit Service 7c31a4
                  unsigned int n_receivers,
Packit Service 7c31a4
                  unsigned long timeout) {
Packit Service 7c31a4
  uv_timer_t timer_handle;
Packit Service 7c31a4
  uint64_t duration;
Packit Service 7c31a4
  uv_loop_t* loop;
Packit Service 7c31a4
  unsigned int i;
Packit Service 7c31a4
Packit Service 7c31a4
  ASSERT(n_senders <= ARRAY_SIZE(senders));
Packit Service 7c31a4
  ASSERT(n_receivers <= ARRAY_SIZE(receivers));
Packit Service 7c31a4
Packit Service 7c31a4
  loop = uv_default_loop();
Packit Service 7c31a4
Packit Service 7c31a4
  n_senders_ = n_senders;
Packit Service 7c31a4
  n_receivers_ = n_receivers;
Packit Service 7c31a4
Packit Service 7c31a4
  if (timeout) {
Packit Service 7c31a4
    ASSERT(0 == uv_timer_init(loop, &timer_handle));
Packit Service 7c31a4
    ASSERT(0 == uv_timer_start(&timer_handle, timeout_cb, timeout, 0));
Packit Service 7c31a4
    /* Timer should not keep loop alive. */
Packit Service 7c31a4
    uv_unref((uv_handle_t*)&timer_handle);
Packit Service 7c31a4
    timed = 1;
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < n_receivers; i++) {
Packit Service 7c31a4
    struct receiver_state* s = receivers + i;
Packit Service 7c31a4
    struct sockaddr_in addr;
Packit Service 7c31a4
    ASSERT(0 == uv_ip4_addr("0.0.0.0", BASE_PORT + i, &addr));
Packit Service 7c31a4
    ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
Packit Service 7c31a4
    ASSERT(0 == uv_udp_bind(&s->udp_handle, (const struct sockaddr*) &addr, 0));
Packit Service 7c31a4
    ASSERT(0 == uv_udp_recv_start(&s->udp_handle, alloc_cb, recv_cb));
Packit Service 7c31a4
    uv_unref((uv_handle_t*)&s->udp_handle);
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  bufs[0] = uv_buf_init(EXPECTED + 0,  10);
Packit Service 7c31a4
  bufs[1] = uv_buf_init(EXPECTED + 10, 10);
Packit Service 7c31a4
  bufs[2] = uv_buf_init(EXPECTED + 20, 10);
Packit Service 7c31a4
  bufs[3] = uv_buf_init(EXPECTED + 30, 10);
Packit Service 7c31a4
  bufs[4] = uv_buf_init(EXPECTED + 40, 5);
Packit Service 7c31a4
Packit Service 7c31a4
  for (i = 0; i < n_senders; i++) {
Packit Service 7c31a4
    struct sender_state* s = senders + i;
Packit Service 7c31a4
    ASSERT(0 == uv_ip4_addr("127.0.0.1",
Packit Service 7c31a4
                            BASE_PORT + (i % n_receivers),
Packit Service 7c31a4
                            &s->addr));
Packit Service 7c31a4
    ASSERT(0 == uv_udp_init(loop, &s->udp_handle));
Packit Service 7c31a4
    ASSERT(0 == uv_udp_send(&s->send_req,
Packit Service 7c31a4
                            &s->udp_handle,
Packit Service 7c31a4
                            bufs,
Packit Service 7c31a4
                            ARRAY_SIZE(bufs),
Packit Service 7c31a4
                            (const struct sockaddr*) &s->addr,
Packit Service 7c31a4
                            send_cb));
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
  duration = uv_hrtime();
Packit Service 7c31a4
  ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
Packit Service 7c31a4
  duration = uv_hrtime() - duration;
Packit Service 7c31a4
  /* convert from nanoseconds to milliseconds */
Packit Service 7c31a4
  duration = duration / (uint64_t) 1e6;
Packit Service 7c31a4
Packit Service 7c31a4
  printf("udp_pummel_%dv%d: %.0f/s received, %.0f/s sent. "
Packit Service 7c31a4
         "%u received, %u sent in %.1f seconds.\n",
Packit Service 7c31a4
         n_receivers,
Packit Service 7c31a4
         n_senders,
Packit Service 7c31a4
         recv_cb_called / (duration / 1000.0),
Packit Service 7c31a4
         send_cb_called / (duration / 1000.0),
Packit Service 7c31a4
         recv_cb_called,
Packit Service 7c31a4
         send_cb_called,
Packit Service 7c31a4
         duration / 1000.0);
Packit Service 7c31a4
Packit Service 7c31a4
  MAKE_VALGRIND_HAPPY();
Packit Service 7c31a4
  return 0;
Packit Service 7c31a4
}
Packit Service 7c31a4
Packit Service 7c31a4
Packit Service 7c31a4
#define X(a, b)                                                               \
Packit Service 7c31a4
  BENCHMARK_IMPL(udp_pummel_##a##v##b) {                                      \
Packit Service 7c31a4
    return pummel(a, b, 0);                                                   \
Packit Service 7c31a4
  }                                                                           \
Packit Service 7c31a4
  BENCHMARK_IMPL(udp_timed_pummel_##a##v##b) {                                \
Packit Service 7c31a4
    return pummel(a, b, TEST_DURATION);                                       \
Packit Service 7c31a4
  }
Packit Service 7c31a4
Packit Service 7c31a4
X(1, 1)
Packit Service 7c31a4
X(1, 10)
Packit Service 7c31a4
X(1, 100)
Packit Service 7c31a4
X(1, 1000)
Packit Service 7c31a4
X(10, 10)
Packit Service 7c31a4
X(10, 100)
Packit Service 7c31a4
X(10, 1000)
Packit Service 7c31a4
X(100, 10)
Packit Service 7c31a4
X(100, 100)
Packit Service 7c31a4
X(100, 1000)
Packit Service 7c31a4
X(1000, 1000)
Packit Service 7c31a4
Packit Service 7c31a4
#undef X