So are we still going with this change, before moving l2fwd to
performance tests?

On Mon, Mar 16, 2015 at 10:26 AM, Savolainen, Petri (Nokia - FI/Espoo)
<[email protected]> wrote:
>
>
>> -----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

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

Reply via email to