app/eventdev: add burst mode for event timer adapter
authorPavan Nikhilesh <pbhagavatula@caviumnetworks.com>
Fri, 6 Apr 2018 15:13:22 +0000 (20:43 +0530)
committerThomas Monjalon <thomas@monjalon.net>
Mon, 16 Apr 2018 09:11:06 +0000 (11:11 +0200)
Add burst mode for event timer adapter that can be selected by passing
--prod_type_timerdev_burst.

Signed-off-by: Pavan Nikhilesh <pbhagavatula@caviumnetworks.com>
Acked-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
Acked-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
app/test-eventdev/evt_options.c
app/test-eventdev/evt_options.h
app/test-eventdev/test_perf_common.c
doc/guides/tools/testeventdev.rst

index 47e37bc..1b60eb2 100644 (file)
@@ -98,6 +98,15 @@ evt_parse_timer_prod_type(struct evt_options *opt, const char *arg __rte_unused)
        return 0;
 }
 
+static int
+evt_parse_timer_prod_type_burst(struct evt_options *opt,
+               const char *arg __rte_unused)
+{
+       opt->prod_type = EVT_PROD_TYPE_EVENT_TIMER_ADPTR;
+       opt->timdev_use_burst = 1;
+       return 0;
+}
+
 static int
 evt_parse_test_name(struct evt_options *opt, const char *arg)
 {
@@ -185,6 +194,8 @@ usage(char *program)
                "\t--prod_type_timerdev : use event timer device as producer.\n"
                "\t                     expity_nsec would be the timeout\n"
                "\t                     in ns.\n"
+               "\t--prod_type_timerdev_burst : use timer device as producer\n"
+               "\t                             burst mode.\n"
                );
        printf("available tests:\n");
        evt_test_dump_names();
@@ -247,6 +258,7 @@ static struct option lgopts[] = {
        { EVT_QUEUE_PRIORITY,      0, 0, 0 },
        { EVT_PROD_ETHDEV,         0, 0, 0 },
        { EVT_PROD_TIMERDEV,       0, 0, 0 },
+       { EVT_PROD_TIMERDEV_BURST, 0, 0, 0 },
        { EVT_HELP,                0, 0, 0 },
        { NULL,                    0, 0, 0 }
 };
@@ -272,6 +284,7 @@ evt_opts_parse_long(int opt_idx, struct evt_options *opt)
                { EVT_QUEUE_PRIORITY, evt_parse_queue_priority},
                { EVT_PROD_ETHDEV, evt_parse_eth_prod_type},
                { EVT_PROD_TIMERDEV, evt_parse_timer_prod_type},
+               { EVT_PROD_TIMERDEV_BURST, evt_parse_timer_prod_type_burst},
        };
 
        for (i = 0; i < RTE_DIM(parsermap); i++) {
index b51d8d5..e5e6327 100644 (file)
@@ -33,6 +33,7 @@
 #define EVT_QUEUE_PRIORITY       ("queue_priority")
 #define EVT_PROD_ETHDEV          ("prod_type_ethdev")
 #define EVT_PROD_TIMERDEV        ("prod_type_timerdev")
+#define EVT_PROD_TIMERDEV_BURST  ("prod_type_timerdev_burst")
 #define EVT_HELP                 ("help")
 
 enum evt_prod_type {
@@ -66,6 +67,7 @@ struct evt_options {
        uint32_t fwd_latency:1;
        uint32_t q_priority:1;
        enum evt_prod_type prod_type;
+       uint8_t timdev_use_burst;
        uint8_t timdev_cnt;
 };
 
@@ -275,7 +277,11 @@ evt_dump_producer_type(struct evt_options *opt)
                evt_dump("nb_ethdev", "%d", rte_eth_dev_count());
                break;
        case EVT_PROD_TYPE_EVENT_TIMER_ADPTR:
-               snprintf(name, EVT_PROD_MAX_NAME_LEN,
+               if (opt->timdev_use_burst)
+                       snprintf(name, EVT_PROD_MAX_NAME_LEN,
+                               "Event timer adapter burst mode producer");
+               else
+                       snprintf(name, EVT_PROD_MAX_NAME_LEN,
                                "Event timer adapter producer");
                evt_dump("nb_timer_adapters", "%d", opt->nb_timer_adptrs);
                evt_dump("max_tmo_nsec", "%"PRIu64"", opt->max_tmo_nsec);
index b6cc00e..a74ab9a 100644 (file)
@@ -133,6 +133,67 @@ perf_event_timer_producer(void *arg)
        return 0;
 }
 
+static inline int
+perf_event_timer_producer_burst(void *arg)
+{
+       int i;
+       struct prod_data *p  = arg;
+       struct test_perf *t = p->t;
+       struct evt_options *opt = t->opt;
+       uint32_t flow_counter = 0;
+       uint64_t count = 0;
+       uint64_t arm_latency = 0;
+       const uint8_t nb_timer_adptrs = opt->nb_timer_adptrs;
+       const uint32_t nb_flows = t->nb_flows;
+       const uint64_t nb_timers = opt->nb_timers;
+       struct rte_mempool *pool = t->pool;
+       struct perf_elt *m[BURST_SIZE + 1] = {NULL};
+       struct rte_event_timer_adapter **adptr = t->timer_adptr;
+       uint64_t timeout_ticks = opt->expiry_nsec / opt->timer_tick_nsec;
+
+       timeout_ticks = opt->optm_timer_tick_nsec ?
+                       (timeout_ticks * opt->timer_tick_nsec)
+                       / opt->optm_timer_tick_nsec : timeout_ticks;
+       timeout_ticks += timeout_ticks ? 0 : 1;
+       const struct rte_event_timer tim = {
+               .ev.op = RTE_EVENT_OP_NEW,
+               .ev.queue_id = p->queue_id,
+               .ev.sched_type = t->opt->sched_type_list[0],
+               .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+               .ev.event_type =  RTE_EVENT_TYPE_TIMER,
+               .state = RTE_EVENT_TIMER_NOT_ARMED,
+               .timeout_ticks = timeout_ticks,
+       };
+
+       if (opt->verbose_level > 1)
+               printf("%s(): lcore %d\n", __func__, rte_lcore_id());
+
+       while (count < nb_timers && t->done == false) {
+               if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0)
+                       continue;
+               for (i = 0; i < BURST_SIZE; i++) {
+                       rte_prefetch0(m[i + 1]);
+                       m[i]->tim = tim;
+                       m[i]->tim.ev.flow_id = flow_counter++ % nb_flows;
+                       m[i]->tim.ev.event_ptr = m[i];
+                       m[i]->timestamp = rte_get_timer_cycles();
+               }
+               rte_event_timer_arm_tmo_tick_burst(
+                               adptr[flow_counter % nb_timer_adptrs],
+                               (struct rte_event_timer **)m,
+                               tim.timeout_ticks,
+                               BURST_SIZE);
+               arm_latency += rte_get_timer_cycles() - m[i - 1]->timestamp;
+               count += BURST_SIZE;
+       }
+       fflush(stdout);
+       rte_delay_ms(1000);
+       printf("%s(): lcore %d Average event timer arm latency = %.3f us\n",
+                       __func__, rte_lcore_id(), (float)(arm_latency / count) /
+                       (rte_get_timer_hz() / 1000000));
+       return 0;
+}
+
 static int
 perf_producer_wrapper(void *arg)
 {
@@ -141,8 +202,12 @@ perf_producer_wrapper(void *arg)
        /* Launch the producer function only in case of synthetic producer. */
        if (t->opt->prod_type == EVT_PROD_TYPE_SYNT)
                return perf_producer(arg);
-       else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR)
+       else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR &&
+                       !t->opt->timdev_use_burst)
                return perf_event_timer_producer(arg);
+       else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR &&
+                       t->opt->timdev_use_burst)
+               return perf_event_timer_producer_burst(arg);
        return 0;
 }
 
index fe8ecff..156702c 100644 (file)
@@ -127,6 +127,10 @@ The following are the application command-line options:
 
         Use event timer adapter as producer.
 
+ * ``--prod_type_timerdev_burst``
+
+        Use burst mode event timer adapter as producer.
+
 Eventdev Tests
 --------------
 
@@ -351,6 +355,7 @@ Supported application command line options are following::
         --fwd_latency
         --queue_priority
         --prod_type_ethdev
+        --prod_type_timerdev_burst
         --prod_type_timerdev
 
 Example
@@ -444,6 +449,7 @@ Supported application command line options are following::
         --worker_deq_depth
         --fwd_latency
         --prod_type_ethdev
+        --prod_type_timerdev_burst
         --prod_type_timerdev
 
 Example