~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to sflphone-common/libs/pjproject/pjlib/src/pjlib-test/ioq_perf.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier
  • Date: 2011-11-25 13:24:12 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20111125132412-dc4qvhyosk74cd42
Tags: 1.0.1-4
Don't assume that arch:all packages will get built (closes: #649726)

Show diffs side-by-side

added added

removed removed

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