Applications like ovn-controller have hundreds of stopwatches.  When
analyzing performance of different parts of the application you don't
always know which exact stopwatch to look at, but going over all of
them manually is tedious.  When looking for slowest parts it's useful
to be able to set a threshold and not show any stopwatches that are
lower.  For example, if the full recompute takes 10 seconds, I'd like
to look at all the stopwatches that are above 1 second, or something
like that.

Adding a new parameter for the stopwatch/show that will achieve
that goal.  For example:

  ovn-appctl stopwatch/show -t 1000 msec

That will show all stopwatches that had a maximum value above or equal
to 1000 msec.  If the stopwatch is in usec or nsec the threshold will
be applied properly with the units conversion.

If the units are not provided, then the value will be checked using
the units of each individual stopwatch.  If all the stopwatches are
in milliseconds, then '-t 10 msec' is equal to '-t 10000 usec',
'-t 10000000 nsec' or just '-t 10'.  Command also accepts the full
version of the argument - '--threshold'.

There are no users for this functionality in OVS, so there is no
documentation to update.

Signed-off-by: Ilya Maximets <[email protected]>
---
 lib/stopwatch.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 52 insertions(+), 3 deletions(-)

diff --git a/lib/stopwatch.c b/lib/stopwatch.c
index 5c59fe71c..ab9df4092 100644
--- a/lib/stopwatch.c
+++ b/lib/stopwatch.c
@@ -295,7 +295,7 @@ stopwatch_show_protected(int argc, const char *argv[], 
struct ds *s)
 {
     struct stopwatch *sw;
 
-    if (argc > 1) {
+    if (argc == 2) {
         sw = shash_find_data(&stopwatches, argv[1]);
         if (!sw) {
             ds_put_cstr(s, "No such stopwatch");
@@ -303,11 +303,59 @@ stopwatch_show_protected(int argc, const char *argv[], 
struct ds *s)
         }
         stopwatch_print(sw, argv[1], s);
     } else {
+        unsigned long long threshold = 0;
         struct shash_node *node;
         int no_samples = 0;
+        int tunits = -1;
+
+        if (argc > 2) {
+            if (strcmp(argv[1], "-t") && strcmp(argv[1], "--threshold")) {
+                ds_put_format(s, "Unknown option: %s", argv[1]);
+                return false;
+            }
+            if (!str_to_ullong(argv[2], 10, &threshold)) {
+                ds_put_format(s, "Invalid threshold: %s", argv[2]);
+                return false;
+            }
+            if (argc == 4) {
+                enum stopwatch_units all[] = { SW_MS, SW_US, SW_NS };
+                for (size_t i = 0; i < ARRAY_SIZE(all); i++) {
+                    if (!strcmp(unit_name[all[i]], argv[3])) {
+                        tunits = all[i];
+                        break;
+                    }
+                }
+                if (tunits < 0) {
+                    ds_put_format(s, "Unknown units: %s"
+                        " (supported: %s, %s or %s).", argv[3],
+                        unit_name[SW_MS], unit_name[SW_US], unit_name[SW_NS]);
+                    return false;
+                }
+            }
+        }
 
         SHASH_FOR_EACH (node, &stopwatches) {
+            double t = threshold;
+            int u = tunits;
+
             sw = node->data;
+
+            /* Convert threshold units into stopwatch units. */
+            if (u >= 0 && u != sw->units) {
+                while (u < sw->units) {
+                    u++;
+                    t *= 1000;
+                }
+                while (u > sw->units) {
+                    u--;
+                    t /= 1000;
+                }
+            }
+
+            if (sw->max < t) {
+                continue;
+            }
+
             if (!sw->n_samples) {
                 no_samples++;
                 continue;
@@ -498,8 +546,9 @@ stopwatch_exit(void)
 static void
 do_init_stopwatch(void)
 {
-    unixctl_command_register("stopwatch/show", "[NAME]", 0, 1,
-                             stopwatch_show, NULL);
+    unixctl_command_register("stopwatch/show",
+                             "[ NAME | -t|--threshold N [unit] ]",
+                             0, 4, stopwatch_show, NULL);
     unixctl_command_register("stopwatch/reset", "[NAME]", 0, 1,
                              stopwatch_reset, NULL);
     guarded_list_init(&stopwatch_commands);
-- 
2.53.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to