From: Petri Savolainen <petri.savolai...@linaro.org>

Added support for multiple threads and -c options to select
number of worker threads.

Signed-off-by: Petri Savolainen <petri.savolai...@linaro.org>
---
/** Email created from pull request 680 
(psavol:master-test-queue-perf-multithread)
 ** https://github.com/Linaro/odp/pull/680
 ** Patch: https://github.com/Linaro/odp/pull/680.patch
 ** Base sha: 1c36bf726387b291d73bee1448cf163527cf5fb0
 ** Merge commit sha: cce6d22c7a83b846bd9589a48869c664f75980ae
 **/
 test/performance/odp_queue_perf.c | 153 ++++++++++++++++++++++--------
 1 file changed, 116 insertions(+), 37 deletions(-)

diff --git a/test/performance/odp_queue_perf.c 
b/test/performance/odp_queue_perf.c
index e1c02f33f..0cda5879b 100644
--- a/test/performance/odp_queue_perf.c
+++ b/test/performance/odp_queue_perf.c
@@ -26,6 +26,15 @@ typedef struct test_options_t {
 
 } test_options_t;
 
+typedef struct test_stat_t {
+       uint64_t rounds;
+       uint64_t events;
+       uint64_t nsec;
+       uint64_t cycles;
+       uint64_t deq_retry;
+
+} test_stat_t;
+
 typedef struct test_global_t {
        odp_barrier_t    barrier;
        test_options_t   options;
@@ -34,6 +43,7 @@ typedef struct test_global_t {
        odp_pool_t       pool;
        odp_queue_t      queue[MAX_QUEUES];
        odph_odpthread_t thread_tbl[ODP_THREAD_COUNT_MAX];
+       test_stat_t      stat[ODP_THREAD_COUNT_MAX];
 
 } test_global_t;
 
@@ -46,8 +56,9 @@ static void print_usage(void)
               "\n"
               "Usage: odp_queue_perf [options]\n"
               "\n"
-              "  -q, --num_queue        Number of queues\n"
-              "  -e, --num_event        Number of events per queue\n"
+              "  -c, --num_cpu          Number of worker threads. Default: 1\n"
+              "  -q, --num_queue        Number of queues. Default: 1\n"
+              "  -e, --num_event        Number of events per queue. Default: 
1\n"
               "  -r, --num_round        Number of rounds\n"
               "  -l, --lockfree         Lockfree queues\n"
               "  -w, --waitfree         Waitfree queues\n"
@@ -63,6 +74,7 @@ static int parse_options(int argc, char *argv[], 
test_options_t *test_options)
        int ret = 0;
 
        static const struct option longopts[] = {
+               {"num_cpu",   required_argument, NULL, 'c'},
                {"num_queue", required_argument, NULL, 'q'},
                {"num_event", required_argument, NULL, 'e'},
                {"num_round", required_argument, NULL, 'r'},
@@ -73,7 +85,7 @@ static int parse_options(int argc, char *argv[], 
test_options_t *test_options)
                {NULL, 0, NULL, 0}
        };
 
-       static const char *shortopts = "+q:e:r:lwsh";
+       static const char *shortopts = "+c:q:e:r:lwsh";
 
        test_options->num_cpu   = 1;
        test_options->num_queue = 1;
@@ -89,6 +101,9 @@ static int parse_options(int argc, char *argv[], 
test_options_t *test_options)
                        break;
 
                switch (opt) {
+               case 'c':
+                       test_options->num_cpu = atoi(optarg);
+                       break;
                case 'q':
                        test_options->num_queue = atoi(optarg);
                        break;
@@ -333,67 +348,66 @@ static int destroy_queues(test_global_t *global)
 
 static int run_test(void *arg)
 {
-       uint64_t c1, c2, diff, ops, nsec;
+       uint64_t c1, c2, cycles, nsec;
        odp_time_t t1, t2;
        odp_event_t ev;
-       uint32_t i, rounds;
+       uint32_t rounds;
+       test_stat_t *stat;
        test_global_t *global = arg;
        test_options_t *test_options = &global->options;
-       odp_queue_t *queue = global->queue;
+       odp_queue_t queue;
        uint64_t num_retry = 0;
+       uint64_t events = 0;
        uint32_t num_queue = test_options->num_queue;
        uint32_t num_round = test_options->num_round;
+       int thr = odp_thread_id();
        int ret = 0;
+       uint32_t i = 0;
+
+       stat = &global->stat[thr];
+
+       /* Start all workers at the same time */
+       odp_barrier_wait(&global->barrier);
 
        t1 = odp_time_local();
        c1 = odp_cpu_cycles();
 
        for (rounds = 0; rounds < num_round; rounds++) {
-               int retry = 0;
+               do {
+                       queue = global->queue[i++];
 
-               for (i = 0; i < num_queue; i++) {
-                       ev = odp_queue_deq(queue[i]);
+                       if (i == num_queue)
+                               i = 0;
 
-                       if (ev == ODP_EVENT_INVALID) {
-                               if (retry < 5) {
-                                       retry++;
-                                       num_retry++;
-                                       continue;
-                               }
+                       ev = odp_queue_deq(queue);
 
-                               printf("Error: Queue deq failed %u\n", i);
-                               ret = -1;
-                               goto error;
-                       }
+                       if (odp_unlikely(ev == ODP_EVENT_INVALID))
+                               num_retry++;
 
-                       retry = 0;
+               } while (ev == ODP_EVENT_INVALID);
 
-                       if (odp_queue_enq(queue[i], ev)) {
-                               printf("Error: Queue enq failed %u\n", i);
-                               ret = -1;
-                               goto error;
-                       }
+               if (odp_queue_enq(queue, ev)) {
+                       printf("Error: Queue enq failed %u\n", i);
+                       ret = -1;
+                       goto error;
                }
+
+               events++;
        }
 
        c2 = odp_cpu_cycles();
        t2 = odp_time_local();
 
-       nsec = odp_time_diff_ns(t2, t1);
-       diff = odp_cpu_cycles_diff(c2, c1);
-       ops = num_round * num_queue;
+       nsec   = odp_time_diff_ns(t2, t1);
+       cycles = odp_cpu_cycles_diff(c2, c1);
 
-       printf("RESULT:\n");
-       printf("  num deq + enq operations: %" PRIu64 "\n", ops);
-       printf("  num events:               %" PRIu64 "\n", ops);
-       printf("  duration (nsec):          %" PRIu64 "\n", nsec);
-       printf("  num cycles:               %" PRIu64 "\n", diff);
-       printf("  cycles per deq + enq:     %.3f\n", (double)diff / ops);
-       printf("  events per sec:           %.3f M\n", (1000.0 * ops) / nsec);
-       printf("  num retries:              %" PRIu64 "\n\n", num_retry);
+       stat->rounds = rounds;
+       stat->events = events;
+       stat->nsec   = nsec;
+       stat->cycles = cycles;
+       stat->deq_retry = num_retry;
 
 error:
-
        return ret;
 }
 
@@ -435,6 +449,69 @@ static int start_workers(test_global_t *global)
        return 0;
 }
 
+static void print_stat(test_global_t *global)
+{
+       int i, num;
+       double events_ave, nsec_ave, cycles_ave, retry_ave;
+       test_options_t *test_options = &global->options;
+       int num_cpu = test_options->num_cpu;
+       uint64_t rounds_sum = 0;
+       uint64_t events_sum = 0;
+       uint64_t nsec_sum = 0;
+       uint64_t cycles_sum = 0;
+       uint64_t retry_sum = 0;
+
+       /* Averages */
+       for (i = 0; i < ODP_THREAD_COUNT_MAX; i++) {
+               rounds_sum   += global->stat[i].rounds;
+               events_sum   += global->stat[i].events;
+               nsec_sum     += global->stat[i].nsec;
+               cycles_sum   += global->stat[i].cycles;
+               retry_sum    += global->stat[i].deq_retry;
+       }
+
+       if (rounds_sum == 0) {
+               printf("No results.\n");
+               return;
+       }
+
+       events_ave   = events_sum / num_cpu;
+       nsec_ave     = nsec_sum / num_cpu;
+       cycles_ave   = cycles_sum / num_cpu;
+       retry_ave    = retry_sum / num_cpu;
+       num = 0;
+
+       printf("RESULTS - per thread (Million events per sec):\n");
+       printf("----------------------------------------------\n");
+       printf("        1      2      3      4      5      6      7      8      
9     10");
+
+       for (i = 0; i < ODP_THREAD_COUNT_MAX; i++) {
+               if (global->stat[i].rounds) {
+                       if ((num % 10) == 0)
+                               printf("\n   ");
+
+                       printf("%6.1f ", (1000.0 * global->stat[i].events) /
+                              global->stat[i].nsec);
+                       num++;
+               }
+       }
+       printf("\n\n");
+
+       printf("RESULTS - per thread average (%i threads):\n", num_cpu);
+       printf("------------------------------------------\n");
+       printf("  duration:                 %.3f msec\n", nsec_ave / 1000000);
+       printf("  num cycles:               %.3f M\n", cycles_ave / 1000000);
+       printf("  cycles per event:         %.3f\n",
+              cycles_ave / events_ave);
+       printf("  deq retries per sec:      %.3f k\n",
+              (1000000.0 * retry_ave) / nsec_ave);
+       printf("  events per sec:           %.3f M\n\n",
+              (1000.0 * events_ave) / nsec_ave);
+
+       printf("TOTAL events per sec:       %.3f M\n\n",
+              (1000.0 * events_sum) / nsec_ave);
+}
+
 int main(int argc, char **argv)
 {
        odp_instance_t instance;
@@ -483,6 +560,8 @@ int main(int argc, char **argv)
        /* Wait workers to exit */
        odph_odpthreads_join(global->thread_tbl);
 
+       print_stat(global);
+
 destroy:
        if (destroy_queues(global)) {
                printf("Error: Destroy queues failed.\n");

Reply via email to