libuv-svace-build

Форк
0
/
benchmark-pound.c 
351 строка · 7.8 Кб
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
/* Update this is you're going to run > 1000 concurrent requests. */
26
#define MAX_CONNS 1000
27

28
#undef NANOSEC
29
#define NANOSEC ((uint64_t) 1e9)
30

31
#undef DEBUG
32
#define DEBUG 0
33

34
struct conn_rec_s;
35

36
typedef void (*setup_fn)(int num, void* arg);
37
typedef void (*make_connect_fn)(struct conn_rec_s* conn);
38
typedef int (*connect_fn)(int num, make_connect_fn make_connect, void* arg);
39

40
/* Base class for tcp_conn_rec and pipe_conn_rec.
41
 * The ordering of fields matters!
42
 */
43
typedef struct conn_rec_s {
44
  int i;
45
  uv_connect_t conn_req;
46
  uv_write_t write_req;
47
  make_connect_fn make_connect;
48
  uv_stream_t stream;
49
} conn_rec;
50

51
typedef struct {
52
  int i;
53
  uv_connect_t conn_req;
54
  uv_write_t write_req;
55
  make_connect_fn make_connect;
56
  uv_tcp_t stream;
57
} tcp_conn_rec;
58

59
typedef struct {
60
  int i;
61
  uv_connect_t conn_req;
62
  uv_write_t write_req;
63
  make_connect_fn make_connect;
64
  uv_pipe_t stream;
65
} pipe_conn_rec;
66

67
static char buffer[] = "QS";
68

69
static uv_loop_t* loop;
70

71
static tcp_conn_rec tcp_conns[MAX_CONNS];
72
static pipe_conn_rec pipe_conns[MAX_CONNS];
73

74
static uint64_t start; /* in ms  */
75
static int closed_streams;
76
static int conns_failed;
77

78
static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
79
static void connect_cb(uv_connect_t* conn_req, int status);
80
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
81
static void close_cb(uv_handle_t* handle);
82

83

84
static void alloc_cb(uv_handle_t* handle,
85
                     size_t suggested_size,
86
                     uv_buf_t* buf) {
87
  static char slab[65536];
88
  buf->base = slab;
89
  buf->len = sizeof(slab);
90
}
91

92

93
static void after_write(uv_write_t* req, int status) {
94
  if (status != 0) {
95
    fprintf(stderr, "write error %s\n", uv_err_name(status));
96
    uv_close((uv_handle_t*)req->handle, close_cb);
97
    conns_failed++;
98
    return;
99
  }
100
}
101

102

103
static void connect_cb(uv_connect_t* req, int status) {
104
  conn_rec* conn;
105
  uv_buf_t buf;
106
  int r;
107

108
  if (status != 0) {
109
#if DEBUG
110
    fprintf(stderr, "connect error %s\n", uv_err_name(status));
111
#endif
112
    uv_close((uv_handle_t*)req->handle, close_cb);
113
    conns_failed++;
114
    return;
115
  }
116

117
  ASSERT_NOT_NULL(req);
118
  ASSERT_OK(status);
119

120
  conn = (conn_rec*)req->data;
121
  ASSERT_NOT_NULL(conn);
122

123
#if DEBUG
124
  printf("connect_cb %d\n", conn->i);
125
#endif
126

127
  r = uv_read_start(&conn->stream, alloc_cb, read_cb);
128
  ASSERT_OK(r);
129

130
  buf.base = buffer;
131
  buf.len = sizeof(buffer) - 1;
132

133
  r = uv_write(&conn->write_req, &conn->stream, &buf, 1, after_write);
134
  ASSERT_OK(r);
135
}
136

137

138
static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
139

140
  ASSERT_NOT_NULL(stream);
141

142
#if DEBUG
143
  printf("read_cb %d\n", p->i);
144
#endif
145

146
  uv_close((uv_handle_t*)stream, close_cb);
147

148
  if (nread < 0) {
149
    if (nread == UV_EOF) {
150
      ;
151
    } else if (nread == UV_ECONNRESET) {
152
      conns_failed++;
153
    } else {
154
      fprintf(stderr, "read error %s\n", uv_err_name(nread));
155
      ASSERT(0);
156
    }
157
  }
158
}
159

160

161
static void close_cb(uv_handle_t* handle) {
162
  conn_rec* p = (conn_rec*)handle->data;
163

164
  ASSERT_NOT_NULL(handle);
165
  closed_streams++;
166

167
#if DEBUG
168
  printf("close_cb %d\n", p->i);
169
#endif
170

171
  if (uv_now(loop) - start < 10000) {
172
    p->make_connect(p);
173
  }
174
}
175

176

177
static void tcp_do_setup(int num, void* arg) {
178
  int i;
179

180
  for (i = 0; i < num; i++) {
181
    tcp_conns[i].i = i;
182
  }
183
}
184

185

186
static void pipe_do_setup(int num, void* arg) {
187
  int i;
188

189
  for (i = 0; i < num; i++) {
190
    pipe_conns[i].i = i;
191
  }
192
}
193

194

195
static void tcp_make_connect(conn_rec* p) {
196
  struct sockaddr_in addr;
197
  tcp_conn_rec* tp;
198
  int r;
199

200
  tp = (tcp_conn_rec*) p;
201

202
  r = uv_tcp_init(loop, (uv_tcp_t*)&p->stream);
203
  ASSERT_OK(r);
204

205
  ASSERT_OK(uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
206

207
  r = uv_tcp_connect(&tp->conn_req,
208
                     (uv_tcp_t*) &p->stream,
209
                     (const struct sockaddr*) &addr,
210
                     connect_cb);
211
  if (r) {
212
    fprintf(stderr, "uv_tcp_connect error %s\n", uv_err_name(r));
213
    ASSERT(0);
214
  }
215

216
#if DEBUG
217
  printf("make connect %d\n", p->i);
218
#endif
219

220
  p->conn_req.data = p;
221
  p->write_req.data = p;
222
  p->stream.data = p;
223
}
224

225

226
static void pipe_make_connect(conn_rec* p) {
227
  int r;
228

229
  r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0);
230
  ASSERT_OK(r);
231

232
  uv_pipe_connect(&((pipe_conn_rec*) p)->conn_req,
233
                  (uv_pipe_t*) &p->stream,
234
                  TEST_PIPENAME,
235
                  connect_cb);
236

237
#if DEBUG
238
  printf("make connect %d\n", p->i);
239
#endif
240

241
  p->conn_req.data = p;
242
  p->write_req.data = p;
243
  p->stream.data = p;
244
}
245

246

247
static int tcp_do_connect(int num, make_connect_fn make_connect, void* arg) {
248
  int i;
249

250
  for (i = 0; i < num; i++) {
251
    tcp_make_connect((conn_rec*)&tcp_conns[i]);
252
    tcp_conns[i].make_connect = make_connect;
253
  }
254

255
  return 0;
256
}
257

258

259
static int pipe_do_connect(int num, make_connect_fn make_connect, void* arg) {
260
  int i;
261

262
  for (i = 0; i < num; i++) {
263
    pipe_make_connect((conn_rec*)&pipe_conns[i]);
264
    pipe_conns[i].make_connect = make_connect;
265
  }
266

267
  return 0;
268
}
269

270

271
static int pound_it(int concurrency,
272
                    const char* type,
273
                    setup_fn do_setup,
274
                    connect_fn do_connect,
275
                    make_connect_fn make_connect,
276
                    void* arg) {
277
  double secs;
278
  int r;
279
  uint64_t start_time; /* in ns */
280
  uint64_t end_time;
281

282
  loop = uv_default_loop();
283

284
  uv_update_time(loop);
285
  start = uv_now(loop);
286

287
  /* Run benchmark for at least five seconds. */
288
  start_time = uv_hrtime();
289

290
  do_setup(concurrency, arg);
291

292
  r = do_connect(concurrency, make_connect, arg);
293
  ASSERT(!r);
294

295
  uv_run(loop, UV_RUN_DEFAULT);
296

297
  end_time = uv_hrtime();
298

299
  /* Number of fractional seconds it took to run the benchmark. */
300
  secs = (double)(end_time - start_time) / NANOSEC;
301

302
  fprintf(stderr, "%s-conn-pound-%d: %.0f accepts/s (%d failed)\n",
303
          type,
304
          concurrency,
305
          closed_streams / secs,
306
          conns_failed);
307
  fflush(stderr);
308

309
  MAKE_VALGRIND_HAPPY(loop);
310
  return 0;
311
}
312

313

314
BENCHMARK_IMPL(tcp4_pound_100) {
315
  return pound_it(100,
316
                  "tcp",
317
                  tcp_do_setup,
318
                  tcp_do_connect,
319
                  tcp_make_connect,
320
                  NULL);
321
}
322

323

324
BENCHMARK_IMPL(tcp4_pound_1000) {
325
  return pound_it(1000,
326
                  "tcp",
327
                  tcp_do_setup,
328
                  tcp_do_connect,
329
                  tcp_make_connect,
330
                  NULL);
331
}
332

333

334
BENCHMARK_IMPL(pipe_pound_100) {
335
  return pound_it(100,
336
                  "pipe",
337
                  pipe_do_setup,
338
                  pipe_do_connect,
339
                  pipe_make_connect,
340
                  NULL);
341
}
342

343

344
BENCHMARK_IMPL(pipe_pound_1000) {
345
  return pound_it(1000,
346
                  "pipe",
347
                  pipe_do_setup,
348
                  pipe_do_connect,
349
                  pipe_make_connect,
350
                  NULL);
351
}
352

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.