blob: 7b203e3f56df43cfd3f3e55de30e01fd09b0d1d2 [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
Benny Prijono32177c02008-06-20 22:44:47 +00003 * Copyright (C)2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono5dcb38d2005-11-21 01:55:47 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include "test.h"
20#include <pjlib.h>
21#include <pj/compat/high_precision.h>
22
23/**
24 * \page page_pjlib_ioqueue_perf_test Test: I/O Queue Performance
25 *
26 * Test the performance of the I/O queue, using typical producer
27 * consumer test. The test should examine the effect of using multiple
28 * threads on the performance.
29 *
30 * This file is <b>pjlib-test/ioq_perf.c</b>
31 *
32 * \include pjlib-test/ioq_perf.c
33 */
34
35#if INCLUDE_IOQUEUE_PERF_TEST
36
37#ifdef _MSC_VER
38# pragma warning ( disable: 4204) // non-constant aggregate initializer
39#endif
40
41#define THIS_FILE "ioq_perf"
42//#define TRACE_(expr) PJ_LOG(3,expr)
43#define TRACE_(expr)
44
45
46static pj_bool_t thread_quit_flag;
47static pj_status_t last_error;
48static unsigned last_error_counter;
49
50/* Descriptor for each producer/consumer pair. */
51typedef struct test_item
52{
53 pj_sock_t server_fd,
54 client_fd;
55 pj_ioqueue_t *ioqueue;
56 pj_ioqueue_key_t *server_key,
57 *client_key;
58 pj_ioqueue_op_key_t recv_op,
59 send_op;
60 int has_pending_send;
61 pj_size_t buffer_size;
62 char *outgoing_buffer;
63 char *incoming_buffer;
64 pj_size_t bytes_sent,
65 bytes_recv;
66} test_item;
67
68/* Callback when data has been read.
69 * Increment item->bytes_recv and ready to read the next data.
70 */
71static void on_read_complete(pj_ioqueue_key_t *key,
72 pj_ioqueue_op_key_t *op_key,
73 pj_ssize_t bytes_read)
74{
Benny Prijonof260e462007-04-30 21:03:32 +000075 test_item *item = (test_item*)pj_ioqueue_get_user_data(key);
Benny Prijono5dcb38d2005-11-21 01:55:47 +000076 pj_status_t rc;
77 int data_is_available = 1;
78
79 //TRACE_((THIS_FILE, " read complete, bytes_read=%d", bytes_read));
80
81 do {
82 if (thread_quit_flag)
83 return;
84
85 if (bytes_read < 0) {
86 pj_status_t rc = -bytes_read;
Benny Prijono2cab3a52006-03-22 19:08:19 +000087 char errmsg[PJ_ERR_MSG_SIZE];
Benny Prijono5dcb38d2005-11-21 01:55:47 +000088
89 if (rc != last_error) {
90 //last_error = rc;
91 pj_strerror(rc, errmsg, sizeof(errmsg));
Benny Prijono2cab3a52006-03-22 19:08:19 +000092 PJ_LOG(3,(THIS_FILE,"...error: read error, bytes_read=%d (%s)",
Benny Prijono5dcb38d2005-11-21 01:55:47 +000093 bytes_read, errmsg));
94 PJ_LOG(3,(THIS_FILE,
95 ".....additional info: total read=%u, total sent=%u",
96 item->bytes_recv, item->bytes_sent));
97 } else {
98 last_error_counter++;
99 }
100 bytes_read = 0;
101
102 } else if (bytes_read == 0) {
103 PJ_LOG(3,(THIS_FILE, "...socket has closed!"));
104 }
105
106 item->bytes_recv += bytes_read;
107
108 /* To assure that the test quits, even if main thread
109 * doesn't have time to run.
110 */
111 if (item->bytes_recv > item->buffer_size * 10000)
112 thread_quit_flag = 1;
113
114 bytes_read = item->buffer_size;
115 rc = pj_ioqueue_recv( key, op_key,
116 item->incoming_buffer, &bytes_read, 0 );
117
118 if (rc == PJ_SUCCESS) {
119 data_is_available = 1;
120 } else if (rc == PJ_EPENDING) {
121 data_is_available = 0;
122 } else {
123 data_is_available = 0;
124 if (rc != last_error) {
125 last_error = rc;
126 app_perror("...error: read error(1)", rc);
127 } else {
128 last_error_counter++;
129 }
130 }
131
132 if (!item->has_pending_send) {
133 pj_ssize_t sent = item->buffer_size;
134 rc = pj_ioqueue_send(item->client_key, &item->send_op,
135 item->outgoing_buffer, &sent, 0);
136 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
137 app_perror("...error: write error", rc);
138 }
139
140 item->has_pending_send = (rc==PJ_EPENDING);
141 }
142
143 } while (data_is_available);
144}
145
146/* Callback when data has been written.
147 * Increment item->bytes_sent and write the next data.
148 */
149static void on_write_complete(pj_ioqueue_key_t *key,
150 pj_ioqueue_op_key_t *op_key,
151 pj_ssize_t bytes_sent)
152{
Benny Prijonof260e462007-04-30 21:03:32 +0000153 test_item *item = (test_item*) pj_ioqueue_get_user_data(key);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000154
155 //TRACE_((THIS_FILE, " write complete: sent = %d", bytes_sent));
156
157 if (thread_quit_flag)
158 return;
159
160 item->has_pending_send = 0;
161 item->bytes_sent += bytes_sent;
162
163 if (bytes_sent <= 0) {
164 PJ_LOG(3,(THIS_FILE, "...error: sending stopped. bytes_sent=%d",
165 bytes_sent));
166 }
167 else {
168 pj_status_t rc;
169
170 bytes_sent = item->buffer_size;
171 rc = pj_ioqueue_send( item->client_key, op_key,
172 item->outgoing_buffer, &bytes_sent, 0);
173 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
174 app_perror("...error: write error", rc);
175 }
176
177 item->has_pending_send = (rc==PJ_EPENDING);
178 }
179}
180
Benny Prijono2cab3a52006-03-22 19:08:19 +0000181struct thread_arg
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000182{
Benny Prijono2cab3a52006-03-22 19:08:19 +0000183 int id;
184 pj_ioqueue_t *ioqueue;
185 unsigned counter;
186};
187
188/* The worker thread. */
189static int worker_thread(void *p)
190{
Benny Prijonof260e462007-04-30 21:03:32 +0000191 struct thread_arg *arg = (struct thread_arg*) p;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000192 const pj_time_val timeout = {0, 100};
193 int rc;
194
195 while (!thread_quit_flag) {
Benny Prijono2cab3a52006-03-22 19:08:19 +0000196
197 ++arg->counter;
198 rc = pj_ioqueue_poll(arg->ioqueue, &timeout);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000199 //TRACE_((THIS_FILE, " thread: poll returned rc=%d", rc));
200 if (rc < 0) {
Benny Prijono2cab3a52006-03-22 19:08:19 +0000201 char errmsg[PJ_ERR_MSG_SIZE];
202 pj_strerror(-rc, errmsg, sizeof(errmsg));
203 PJ_LOG(3, (THIS_FILE,
204 "...error in pj_ioqueue_poll() in thread %d "
205 "after %d loop: %s [pj_status_t=%d]",
206 arg->id, arg->counter, errmsg, -rc));
207 //return -1;
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000208 }
209 }
210 return 0;
211}
212
213/* Calculate the bandwidth for the specific test configuration.
214 * The test is simple:
215 * - create sockpair_cnt number of producer-consumer socket pair.
216 * - create thread_cnt number of worker threads.
217 * - each producer will send buffer_size bytes data as fast and
218 * as soon as it can.
219 * - each consumer will read buffer_size bytes of data as fast
220 * as it could.
221 * - measure the total bytes received by all consumers during a
222 * period of time.
223 */
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000224static int perform_test(pj_bool_t allow_concur,
225 int sock_type, const char *type_name,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000226 unsigned thread_cnt, unsigned sockpair_cnt,
227 pj_size_t buffer_size,
228 pj_size_t *p_bandwidth)
229{
230 enum { MSEC_DURATION = 5000 };
231 pj_pool_t *pool;
232 test_item *items;
233 pj_thread_t **thread;
234 pj_ioqueue_t *ioqueue;
235 pj_status_t rc;
236 pj_ioqueue_callback ioqueue_callback;
237 pj_uint32_t total_elapsed_usec, total_received;
238 pj_highprec_t bandwidth;
239 pj_timestamp start, stop;
240 unsigned i;
241
242 TRACE_((THIS_FILE, " starting test.."));
243
244 ioqueue_callback.on_read_complete = &on_read_complete;
245 ioqueue_callback.on_write_complete = &on_write_complete;
246
247 thread_quit_flag = 0;
248
249 pool = pj_pool_create(mem, NULL, 4096, 4096, NULL);
250 if (!pool)
251 return -10;
252
Benny Prijonof260e462007-04-30 21:03:32 +0000253 items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item));
254 thread = (pj_thread_t**)
255 pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000256
257 TRACE_((THIS_FILE, " creating ioqueue.."));
258 rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue);
259 if (rc != PJ_SUCCESS) {
260 app_perror("...error: unable to create ioqueue", rc);
261 return -15;
262 }
263
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000264 rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur);
265 if (rc != PJ_SUCCESS) {
266 app_perror("...error: pj_ioqueue_set_default_concurrency()", rc);
267 return -16;
268 }
269
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000270 /* Initialize each producer-consumer pair. */
271 for (i=0; i<sockpair_cnt; ++i) {
272 pj_ssize_t bytes;
273
274 items[i].ioqueue = ioqueue;
275 items[i].buffer_size = buffer_size;
Benny Prijonof260e462007-04-30 21:03:32 +0000276 items[i].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size);
277 items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000278 items[i].bytes_recv = items[i].bytes_sent = 0;
279
280 /* randomize outgoing buffer. */
281 pj_create_random_string(items[i].outgoing_buffer, buffer_size);
282
283 /* Create socket pair. */
284 TRACE_((THIS_FILE, " calling socketpair.."));
Benny Prijono8ab968f2007-07-20 08:08:30 +0000285 rc = app_socketpair(pj_AF_INET(), sock_type, 0,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000286 &items[i].server_fd, &items[i].client_fd);
287 if (rc != PJ_SUCCESS) {
288 app_perror("...error: unable to create socket pair", rc);
289 return -20;
290 }
291
292 /* Register server socket to ioqueue. */
293 TRACE_((THIS_FILE, " register(1).."));
294 rc = pj_ioqueue_register_sock(pool, ioqueue,
295 items[i].server_fd,
296 &items[i], &ioqueue_callback,
297 &items[i].server_key);
298 if (rc != PJ_SUCCESS) {
299 app_perror("...error: registering server socket to ioqueue", rc);
300 return -60;
301 }
302
303 /* Register client socket to ioqueue. */
304 TRACE_((THIS_FILE, " register(2).."));
305 rc = pj_ioqueue_register_sock(pool, ioqueue,
306 items[i].client_fd,
307 &items[i], &ioqueue_callback,
308 &items[i].client_key);
309 if (rc != PJ_SUCCESS) {
310 app_perror("...error: registering server socket to ioqueue", rc);
311 return -70;
312 }
313
314 /* Start reading. */
315 TRACE_((THIS_FILE, " pj_ioqueue_recv.."));
316 bytes = items[i].buffer_size;
317 rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op,
318 items[i].incoming_buffer, &bytes,
319 0);
320 if (rc != PJ_EPENDING) {
321 app_perror("...error: pj_ioqueue_recv", rc);
322 return -73;
323 }
324
325 /* Start writing. */
326 TRACE_((THIS_FILE, " pj_ioqueue_write.."));
327 bytes = items[i].buffer_size;
Benny Prijono37e8d332006-01-20 21:03:36 +0000328 rc = pj_ioqueue_send(items[i].client_key, &items[i].send_op,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000329 items[i].outgoing_buffer, &bytes, 0);
330 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
331 app_perror("...error: pj_ioqueue_write", rc);
332 return -76;
333 }
334
335 items[i].has_pending_send = (rc==PJ_EPENDING);
336 }
337
338 /* Create the threads. */
339 for (i=0; i<thread_cnt; ++i) {
Benny Prijono2cab3a52006-03-22 19:08:19 +0000340 struct thread_arg *arg;
341
Benny Prijono64898b52007-05-01 06:36:15 +0000342 arg = (struct thread_arg*) pj_pool_zalloc(pool, sizeof(*arg));
Benny Prijono2cab3a52006-03-22 19:08:19 +0000343 arg->id = i;
344 arg->ioqueue = ioqueue;
345 arg->counter = 0;
346
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000347 rc = pj_thread_create( pool, NULL,
348 &worker_thread,
Benny Prijono2cab3a52006-03-22 19:08:19 +0000349 arg,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000350 PJ_THREAD_DEFAULT_STACK_SIZE,
351 PJ_THREAD_SUSPENDED, &thread[i] );
352 if (rc != PJ_SUCCESS) {
353 app_perror("...error: unable to create thread", rc);
354 return -80;
355 }
356 }
357
358 /* Mark start time. */
359 rc = pj_get_timestamp(&start);
360 if (rc != PJ_SUCCESS)
361 return -90;
362
363 /* Start the thread. */
364 TRACE_((THIS_FILE, " resuming all threads.."));
365 for (i=0; i<thread_cnt; ++i) {
366 rc = pj_thread_resume(thread[i]);
367 if (rc != 0)
368 return -100;
369 }
370
371 /* Wait for MSEC_DURATION seconds.
372 * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually,
373 * but unfortunately it doesn't work when system doesn't employ
374 * timeslicing for threads.
375 */
376 TRACE_((THIS_FILE, " wait for few seconds.."));
377 do {
378 pj_thread_sleep(1);
379
380 /* Mark end time. */
381 rc = pj_get_timestamp(&stop);
382
383 if (thread_quit_flag) {
384 TRACE_((THIS_FILE, " transfer limit reached.."));
385 break;
386 }
387
388 if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) {
389 TRACE_((THIS_FILE, " time limit reached.."));
390 break;
391 }
392
393 } while (1);
394
395 /* Terminate all threads. */
396 TRACE_((THIS_FILE, " terminating all threads.."));
397 thread_quit_flag = 1;
398
399 for (i=0; i<thread_cnt; ++i) {
400 TRACE_((THIS_FILE, " join thread %d..", i));
401 pj_thread_join(thread[i]);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000402 }
403
404 /* Close all sockets. */
405 TRACE_((THIS_FILE, " closing all sockets.."));
406 for (i=0; i<sockpair_cnt; ++i) {
407 pj_ioqueue_unregister(items[i].server_key);
408 pj_ioqueue_unregister(items[i].client_key);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000409 }
410
Benny Prijono2cab3a52006-03-22 19:08:19 +0000411 /* Destroy threads */
412 for (i=0; i<thread_cnt; ++i) {
413 pj_thread_destroy(thread[i]);
414 }
415
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000416 /* Destroy ioqueue. */
417 TRACE_((THIS_FILE, " destroying ioqueue.."));
418 pj_ioqueue_destroy(ioqueue);
419
420 /* Calculate actual time in usec. */
421 total_elapsed_usec = pj_elapsed_usec(&start, &stop);
422
423 /* Calculate total bytes received. */
424 total_received = 0;
425 for (i=0; i<sockpair_cnt; ++i) {
426 total_received = items[i].bytes_recv;
427 }
428
429 /* bandwidth = total_received*1000/total_elapsed_usec */
430 bandwidth = total_received;
431 pj_highprec_mul(bandwidth, 1000);
432 pj_highprec_div(bandwidth, total_elapsed_usec);
433
434 *p_bandwidth = (pj_uint32_t)bandwidth;
435
Benny Prijonoac52df42006-03-25 10:06:00 +0000436 PJ_LOG(3,(THIS_FILE, " %.4s %2d %2d %8d KB/s",
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000437 type_name, thread_cnt, sockpair_cnt,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000438 *p_bandwidth));
439
440 /* Done. */
441 pj_pool_release(pool);
442
443 TRACE_((THIS_FILE, " done.."));
444 return 0;
445}
446
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000447static int ioqueue_perf_test_imp(pj_bool_t allow_concur)
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000448{
449 enum { BUF_SIZE = 512 };
450 int i, rc;
451 struct {
452 int type;
453 const char *type_name;
454 int thread_cnt;
455 int sockpair_cnt;
456 } test_param[] =
457 {
Benny Prijono8ab968f2007-07-20 08:08:30 +0000458 { pj_SOCK_DGRAM(), "udp", 1, 1},
459 { pj_SOCK_DGRAM(), "udp", 1, 2},
460 { pj_SOCK_DGRAM(), "udp", 1, 4},
461 { pj_SOCK_DGRAM(), "udp", 1, 8},
462 { pj_SOCK_DGRAM(), "udp", 2, 1},
463 { pj_SOCK_DGRAM(), "udp", 2, 2},
464 { pj_SOCK_DGRAM(), "udp", 2, 4},
465 { pj_SOCK_DGRAM(), "udp", 2, 8},
466 { pj_SOCK_DGRAM(), "udp", 4, 1},
467 { pj_SOCK_DGRAM(), "udp", 4, 2},
468 { pj_SOCK_DGRAM(), "udp", 4, 4},
469 { pj_SOCK_DGRAM(), "udp", 4, 8},
470 { pj_SOCK_DGRAM(), "udp", 4, 16},
471 { pj_SOCK_STREAM(), "tcp", 1, 1},
472 { pj_SOCK_STREAM(), "tcp", 1, 2},
473 { pj_SOCK_STREAM(), "tcp", 1, 4},
474 { pj_SOCK_STREAM(), "tcp", 1, 8},
475 { pj_SOCK_STREAM(), "tcp", 2, 1},
476 { pj_SOCK_STREAM(), "tcp", 2, 2},
477 { pj_SOCK_STREAM(), "tcp", 2, 4},
478 { pj_SOCK_STREAM(), "tcp", 2, 8},
479 { pj_SOCK_STREAM(), "tcp", 4, 1},
480 { pj_SOCK_STREAM(), "tcp", 4, 2},
481 { pj_SOCK_STREAM(), "tcp", 4, 4},
482 { pj_SOCK_STREAM(), "tcp", 4, 8},
483 { pj_SOCK_STREAM(), "tcp", 4, 16},
Benny Prijono2cab3a52006-03-22 19:08:19 +0000484/*
Benny Prijono8ab968f2007-07-20 08:08:30 +0000485 { pj_SOCK_DGRAM(), "udp", 32, 1},
486 { pj_SOCK_DGRAM(), "udp", 32, 1},
487 { pj_SOCK_DGRAM(), "udp", 32, 1},
488 { pj_SOCK_DGRAM(), "udp", 32, 1},
489 { pj_SOCK_DGRAM(), "udp", 1, 32},
490 { pj_SOCK_DGRAM(), "udp", 1, 32},
491 { pj_SOCK_DGRAM(), "udp", 1, 32},
492 { pj_SOCK_DGRAM(), "udp", 1, 32},
493 { pj_SOCK_STREAM(), "tcp", 32, 1},
494 { pj_SOCK_STREAM(), "tcp", 32, 1},
495 { pj_SOCK_STREAM(), "tcp", 32, 1},
496 { pj_SOCK_STREAM(), "tcp", 32, 1},
497 { pj_SOCK_STREAM(), "tcp", 1, 32},
498 { pj_SOCK_STREAM(), "tcp", 1, 32},
499 { pj_SOCK_STREAM(), "tcp", 1, 32},
500 { pj_SOCK_STREAM(), "tcp", 1, 32},
Benny Prijono2cab3a52006-03-22 19:08:19 +0000501*/
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000502 };
503 pj_size_t best_bandwidth;
504 int best_index = 0;
505
506 PJ_LOG(3,(THIS_FILE, " Benchmarking %s ioqueue:", pj_ioqueue_name()));
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000507 PJ_LOG(3,(THIS_FILE, " Testing with concurency=%d", allow_concur));
Benny Prijono2cab3a52006-03-22 19:08:19 +0000508 PJ_LOG(3,(THIS_FILE, " ======================================="));
509 PJ_LOG(3,(THIS_FILE, " Type Threads Skt.Pairs Bandwidth"));
510 PJ_LOG(3,(THIS_FILE, " ======================================="));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000511
512 best_bandwidth = 0;
Benny Prijonoa1e69682007-05-11 15:14:34 +0000513 for (i=0; i<(int)(sizeof(test_param)/sizeof(test_param[0])); ++i) {
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000514 pj_size_t bandwidth;
515
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000516 rc = perform_test(allow_concur,
517 test_param[i].type,
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000518 test_param[i].type_name,
519 test_param[i].thread_cnt,
520 test_param[i].sockpair_cnt,
521 BUF_SIZE,
522 &bandwidth);
523 if (rc != 0)
524 return rc;
525
526 if (bandwidth > best_bandwidth)
527 best_bandwidth = bandwidth, best_index = i;
528
Benny Prijono2cab3a52006-03-22 19:08:19 +0000529 /* Give it a rest before next test, to allow system to close the
530 * sockets properly.
531 */
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000532 pj_thread_sleep(500);
533 }
534
535 PJ_LOG(3,(THIS_FILE,
536 " Best: Type=%s Threads=%d, Skt.Pairs=%d, Bandwidth=%u KB/s",
537 test_param[best_index].type_name,
538 test_param[best_index].thread_cnt,
539 test_param[best_index].sockpair_cnt,
540 best_bandwidth));
541 PJ_LOG(3,(THIS_FILE, " (Note: packet size=%d, total errors=%u)",
542 BUF_SIZE, last_error_counter));
543 return 0;
544}
545
Benny Prijonoe3f79fd2008-02-13 15:17:28 +0000546/*
547 * main test entry.
548 */
549int ioqueue_perf_test(void)
550{
551 int rc;
552
553 rc = ioqueue_perf_test_imp(PJ_TRUE);
554 if (rc != 0)
555 return rc;
556
557 rc = ioqueue_perf_test_imp(PJ_FALSE);
558 if (rc != 0)
559 return rc;
560
561 return 0;
562}
563
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000564#else
565/* To prevent warning about "translation unit is empty"
566 * when this test is disabled.
567 */
568int dummy_uiq_perf_test;
569#endif /* INCLUDE_IOQUEUE_PERF_TEST */
570
571