PageRenderTime 21ms CodeModel.GetById 9ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/test/benchmark-udp-packet-storm.c

http://github.com/joyent/libuv
C | 247 lines | 151 code | 75 blank | 21 comment | 22 complexity | b2402f9eb9d5e939a1c022a62f90932b MD5 | raw file
  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#include <string.h>
 28
 29#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN" /* "Take eight!" */
 30
 31#define TEST_DURATION 5000 /* ms */
 32
 33#define MAX_SENDERS   1000
 34#define MAX_RECEIVERS 1000
 35
 36#define BASE_PORT 12345
 37
 38static uv_loop_t* loop;
 39
 40static int n_senders_;
 41static int n_receivers_;
 42static uv_udp_t senders[MAX_SENDERS];
 43static uv_udp_t receivers[MAX_RECEIVERS];
 44static uv_buf_t bufs[5];
 45
 46static int send_cb_called;
 47static int recv_cb_called;
 48static int close_cb_called;
 49static int stopping = 0;
 50
 51typedef struct {
 52  struct sockaddr_in addr;
 53} sender_state_t;
 54
 55
 56static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) {
 57  static char slab[65536];
 58  ASSERT(suggested_size <= sizeof slab);
 59  return uv_buf_init(slab, sizeof slab);
 60}
 61
 62
 63static void send_cb(uv_udp_send_t* req, int status) {
 64  sender_state_t* ss;
 65  int r;
 66
 67  if (stopping) {
 68    return;
 69  }
 70
 71  ASSERT(req != NULL);
 72  ASSERT(status == 0);
 73
 74  ss = req->data;
 75
 76  r = uv_udp_send(req, req->handle, bufs, ARRAY_SIZE(bufs), ss->addr, send_cb);
 77  ASSERT(r == 0);
 78
 79  req->data = ss;
 80
 81  send_cb_called++;
 82}
 83
 84
 85static void recv_cb(uv_udp_t* handle,
 86                    ssize_t nread,
 87                    uv_buf_t buf,
 88                    struct sockaddr* addr,
 89                    unsigned flags) {
 90  if (nread == 0)
 91    return;
 92
 93  if (nread == -1) {
 94    ASSERT(uv_last_error(loop).code == UV_EINTR); /* FIXME change error code */
 95    return;
 96  }
 97
 98  ASSERT(addr->sa_family == AF_INET);
 99  ASSERT(!memcmp(buf.base, EXPECTED, nread));
100
101  recv_cb_called++;
102}
103
104
105static void close_cb(uv_handle_t* handle) {
106  ASSERT(handle != NULL);
107  close_cb_called++;
108}
109
110
111static void timeout_cb(uv_timer_t* timer, int status) {
112  int i;
113
114  stopping = 1;
115
116  for (i = 0; i < n_senders_; i++)
117    uv_close((uv_handle_t*)&senders[i], close_cb);
118
119  for (i = 0; i < n_receivers_; i++)
120    uv_close((uv_handle_t*)&receivers[i], close_cb);
121}
122
123
124static int do_packet_storm(int n_senders, int n_receivers) {
125  uv_timer_t timeout;
126  sender_state_t *ss;
127  uv_udp_send_t* req;
128  uv_udp_t* handle;
129  int i;
130  int r;
131
132  ASSERT(n_senders <= MAX_SENDERS);
133  ASSERT(n_receivers <= MAX_RECEIVERS);
134
135  loop = uv_default_loop();
136
137  n_senders_ = n_senders;
138  n_receivers_ = n_receivers;
139
140  r = uv_timer_init(loop, &timeout);
141  ASSERT(r == 0);
142
143  r = uv_timer_start(&timeout, timeout_cb, TEST_DURATION, 0);
144  ASSERT(r == 0);
145
146  /* Timer should not keep loop alive. */
147  uv_unref(loop);
148
149  for (i = 0; i < n_receivers; i++) {
150    struct sockaddr_in addr;
151    handle = &receivers[i];
152
153    r = uv_udp_init(loop, handle);
154    ASSERT(r == 0);
155
156    addr = uv_ip4_addr("0.0.0.0", BASE_PORT + i);
157
158    r = uv_udp_bind(handle, addr, 0);
159    ASSERT(r == 0);
160
161    r = uv_udp_recv_start(handle, alloc_cb, recv_cb);
162    ASSERT(r == 0);
163  }
164
165  bufs[0] = uv_buf_init(EXPECTED + 0,  10);
166  bufs[1] = uv_buf_init(EXPECTED + 10, 10);
167  bufs[2] = uv_buf_init(EXPECTED + 20, 10);
168  bufs[3] = uv_buf_init(EXPECTED + 30, 10);
169  bufs[4] = uv_buf_init(EXPECTED + 40, 5);
170
171  for (i = 0; i < n_senders; i++) {
172    handle = &senders[i];
173
174    r = uv_udp_init(loop, handle);
175    ASSERT(r == 0);
176
177    req = malloc(sizeof(*req) + sizeof(*ss));
178
179    ss = (void*)(req + 1);
180    ss->addr = uv_ip4_addr("127.0.0.1", BASE_PORT + (i % n_receivers));
181
182    r = uv_udp_send(req, handle, bufs, ARRAY_SIZE(bufs), ss->addr, send_cb);
183    ASSERT(r == 0);
184
185    req->data = ss;
186  }
187
188  uv_run(loop);
189
190  printf("udp_packet_storm_%dv%d: %.0f/s received, %.0f/s sent\n",
191         n_receivers,
192         n_senders,
193         recv_cb_called / (TEST_DURATION / 1000.0),
194         send_cb_called / (TEST_DURATION / 1000.0));
195
196  return 0;
197}
198
199
200BENCHMARK_IMPL(udp_packet_storm_1v1) {
201  return do_packet_storm(1, 1);
202}
203
204
205BENCHMARK_IMPL(udp_packet_storm_1v10) {
206  return do_packet_storm(1, 10);
207}
208
209
210BENCHMARK_IMPL(udp_packet_storm_1v100) {
211  return do_packet_storm(1, 100);
212}
213
214
215BENCHMARK_IMPL(udp_packet_storm_1v1000) {
216  return do_packet_storm(1, 1000);
217}
218
219
220BENCHMARK_IMPL(udp_packet_storm_10v10) {
221  return do_packet_storm(10, 10);
222}
223
224
225BENCHMARK_IMPL(udp_packet_storm_10v100) {
226  return do_packet_storm(10, 100);
227}
228
229
230BENCHMARK_IMPL(udp_packet_storm_10v1000) {
231  return do_packet_storm(10, 1000);
232}
233
234
235BENCHMARK_IMPL(udp_packet_storm_100v100) {
236  return do_packet_storm(100, 100);
237}
238
239
240BENCHMARK_IMPL(udp_packet_storm_100v1000) {
241  return do_packet_storm(100, 1000);
242}
243
244
245BENCHMARK_IMPL(udp_packet_storm_1000v1000) {
246  return do_packet_storm(1000, 1000);
247}