On 03/16/15 13:22, Ciprian Barbu wrote:
So are we still going with this change, before moving l2fwd to
performance tests?
I think yes, why not? Even if after then it will be not hard to ally that patch.


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.

Ok, will change it. If each thread will have variable for that counter and pointer to that variable will be provided to main with thread args that has to work, right?

       }

  /* 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