> -----Original Message-----
> From: [email protected] [mailto:lng-odp-
> [email protected]] On Behalf Of ext Maxim Uvarov
> Sent: Friday, March 13, 2015 5:04 PM
> To: [email protected]
> Subject: [lng-odp] [PATCHv2 1/2] example: l2fwd print packets per second
> 
> Current print in l2fwd is not useful with slow links and
> also it's hard to say how fast does it work. Print pps
> and packets drops.
> 
> Signed-off-by: Maxim Uvarov <[email protected]>
> ---
>  example/l2fwd/odp_l2fwd.c | 98 ++++++++++++++++++++++++++++++++++--------
> -----
>  1 file changed, 71 insertions(+), 27 deletions(-)
> 
> diff --git a/example/l2fwd/odp_l2fwd.c b/example/l2fwd/odp_l2fwd.c
> index d062a72..0299278 100644
> --- a/example/l2fwd/odp_l2fwd.c
> +++ b/example/l2fwd/odp_l2fwd.c
> @@ -73,6 +73,8 @@ typedef struct {
>       int if_count;           /**< Number of interfaces to be used */
>       char **if_names;        /**< Array of pointers to interface names */
>       int mode;               /**< Packet IO mode */
> +     int time;               /**< Time in seconds to run. */
> +     int accuracy;           /**< Number of seconds to get and print
> statistics */
>  } appl_args_t;
> 
>  /**
> @@ -104,6 +106,15 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args);
>  static void print_info(char *progname, appl_args_t *appl_args);
>  static void usage(char *progname);
> 
> +/* speed and stats */
> +typedef struct {
> +     uint64_t packets[MAX_WORKERS];
> +     uint64_t drops[MAX_WORKERS];
> +} stats_t;
> +
> +static stats_t stats;
> +static int exit_threads;
> +
>  /**
>   * Packet IO worker thread using ODP queues
>   *
> @@ -115,8 +126,6 @@ static void *pktio_queue_thread(void *arg)
>       odp_queue_t outq_def;
>       odp_packet_t pkt;
>       odp_event_t ev;
> -     unsigned long pkt_cnt = 0;
> -     unsigned long err_cnt = 0;
> 
>       (void)arg;
> 
> @@ -125,14 +134,14 @@ static void *pktio_queue_thread(void *arg)
>       printf("[%02i] QUEUE mode\n", thr);
> 
>       /* Loop packets */
> -     for (;;) {
> +     while (!exit_threads) {
>               /* Use schedule to get buf from any input queue */
>               ev  = odp_schedule(NULL, ODP_SCHED_WAIT);
>               pkt = odp_packet_from_event(ev);
> 
>               /* Drop packets with errors */
>               if (odp_unlikely(drop_err_pkts(&pkt, 1) == 0)) {
> -                     EXAMPLE_ERR("Drop frame - err_cnt:%lu\n", ++err_cnt);
> +                     stats.drops[thr] += 1;
>                       continue;
>               }
> 
> @@ -141,11 +150,7 @@ static void *pktio_queue_thread(void *arg)
>               /* Enqueue the packet for output */
>               odp_queue_enq(outq_def, ev);
> 
> -             /* Print packet counts every once in a while */
> -             if (odp_unlikely(pkt_cnt++ % 100000 == 0)) {
> -                     printf("  [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
> -                     fflush(NULL);
> -             }
> +             stats.packets[thr] += 1;

Per thread statistics should be forced to separate cache lines. Now this line 
is likely to cause a cache miss per packet due to false sharing.

>       }
> 
>  /* unreachable */
> @@ -186,9 +191,6 @@ static void *pktio_ifburst_thread(void *arg)
>       thread_args_t *thr_args;
>       int pkts, pkts_ok;
>       odp_packet_t pkt_tbl[MAX_PKT_BURST];
> -     unsigned long pkt_cnt = 0;
> -     unsigned long err_cnt = 0;
> -     unsigned long tmp = 0;
>       int src_idx, dst_idx;
>       odp_pktio_t pktio_src, pktio_dst;
> 
> @@ -208,7 +210,7 @@ static void *pktio_ifburst_thread(void *arg)
>              odp_pktio_to_u64(pktio_src), odp_pktio_to_u64(pktio_dst));
> 
>       /* Loop packets */
> -     for (;;) {
> +     while (!exit_threads) {
>               pkts = odp_pktio_recv(pktio_src, pkt_tbl, MAX_PKT_BURST);
>               if (pkts <= 0)
>                       continue;
> @@ -218,23 +220,13 @@ static void *pktio_ifburst_thread(void *arg)
>               if (pkts_ok > 0)
>                       odp_pktio_send(pktio_dst, pkt_tbl, pkts_ok);
> 
> -             if (odp_unlikely(pkts_ok != pkts)) {
> -                     err_cnt += pkts-pkts_ok;
> -                     EXAMPLE_ERR("Dropped frames:%u - err_cnt:%lu\n",
> -                                 pkts-pkts_ok, err_cnt);
> -             }
> +             if (odp_unlikely(pkts_ok != pkts))
> +                     stats.drops[thr] += pkts - pkts_ok;
> 
>               if (pkts_ok == 0)
>                       continue;
> 
> -             /* Print packet counts every once in a while */
> -             tmp += pkts_ok;
> -             if (odp_unlikely(tmp >= 100000 || pkt_cnt == 0)) {
> -                     pkt_cnt += tmp;
> -                     tmp = 0;
> -                     printf("  [%02i] pkt_cnt:%lu\n", thr, pkt_cnt);
> -                     fflush(NULL);
> -             }
> +             stats.packets[thr] += pkts_ok;
>       }
> 
>  /* unreachable */
> @@ -295,6 +287,41 @@ static odp_pktio_t create_pktio(const char *dev,
> odp_pool_t pool,
>       return pktio;
>  }
> 
> +static void print_speed_stats(int num_workers, int duration, int timeout)
> +{
> +     stats_t old_stats, new_stats;
> +     uint64_t pps, maximum_pps = 0;
> +     uint64_t errors;
> +     int i;
> +     int elapsed = 0;
> +
> +     do {
> +             memcpy(&old_stats, &stats, sizeof(stats_t));

No need to copy two times. One copy, destination pointer ping-pong and time 
measurement over the entire loop would do the trick.

-Petri


> +             sleep(timeout);
> +             memcpy(&new_stats, &stats, sizeof(stats_t));
> +
> +             for (i = 0, pps = 0; i < num_workers; i++)
> +                     pps += new_stats.packets[i] - old_stats.packets[i];
> +             pps = pps / timeout;
> +             if (pps > maximum_pps)
> +                     maximum_pps = pps;
> +
> +             printf("%" PRIu64 " pps, %" PRIu64 " max pps, ",  pps,
> +                    maximum_pps);
> +
> +             for (i = 0, errors = 0; i < num_workers; i++)
> +                     errors += new_stats.drops[i] - old_stats.drops[i];
> +             errors = errors / timeout;
> +
> +             printf(" %" PRIu64 " drops\n", errors);
> +             elapsed += timeout;
> +     } while (elapsed < duration);
> +
> +     printf("TEST RESULT: %" PRIu64 " maximum packets per second.\n",
> +            maximum_pps);
> +     return;
> +}
> +
>  /**
>   * ODP L2 forwarding main function
>   */
> @@ -412,6 +439,11 @@ int main(int argc, char *argv[])
>               cpu = odp_cpumask_next(&cpumask, cpu);
>       }
> 
> +     print_speed_stats(num_workers, gbl_args->appl.time,
> +                       gbl_args->appl.accuracy);
> +
> +     exit_threads = 1;
> +
>       /* Master thread waits for other threads to exit */
>       odph_linux_pthread_join(thread_tbl, num_workers);
> 
> @@ -467,16 +499,20 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
>       int i;
>       static struct option longopts[] = {
>               {"count", required_argument, NULL, 'c'},
> +             {"time", required_argument, NULL, 't'},
> +             {"accuracy", required_argument, NULL, 'a'},
>               {"interface", required_argument, NULL, 'i'},    /* return 'i'
> */
>               {"mode", required_argument, NULL, 'm'},         /* return 'm'
> */
>               {"help", no_argument, NULL, 'h'},               /* return 'h' */
>               {NULL, 0, NULL, 0}
>       };
> 
> +     appl_args->time =  0;
> +     appl_args->accuracy = 10; /* get and print pps stats each X seconds
> */
>       appl_args->mode = -1; /* Invalid, must be changed by parsing */
> 
>       while (1) {
> -             opt = getopt_long(argc, argv, "+c:i:m:h",
> +             opt = getopt_long(argc, argv, "+c:+t:+a:i:m:h",
>                                 longopts, &long_index);
> 
>               if (opt == -1)
> @@ -486,6 +522,12 @@ static void parse_args(int argc, char *argv[],
> appl_args_t *appl_args)
>               case 'c':
>                       appl_args->cpu_count = atoi(optarg);
>                       break;
> +             case 't':
> +                     appl_args->time = atoi(optarg);
> +                     break;
> +             case 'a':
> +                     appl_args->accuracy = atoi(optarg);
> +                     break;
>                       /* parse packet-io interface names */
>               case 'i':
>                       len = strlen(optarg);
> @@ -612,6 +654,8 @@ static void usage(char *progname)
>              "\n"
>              "Optional OPTIONS\n"
>              "  -c, --count <number> CPU count.\n"
> +            "  -t, --time  <number> Time in seconds to run.\n"
> +            "  -a, --accuracy <number> Time in seconds get print
> statistics.\n"
>              "  -h, --help           Display help and exit.\n\n"
>              " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
>              "                        ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
> --
> 1.9.1
> 
> 
> _______________________________________________
> lng-odp mailing list
> [email protected]
> http://lists.linaro.org/mailman/listinfo/lng-odp

_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to