[ovs-dev] [PATCH V3 1/3] coverage: Reimplement the "ovs-appclt coverage/show" command

Andy Zhou azhou at nicira.com
Fri Aug 16 00:39:33 UTC 2013


Thanks for rebasing.


On Wed, Aug 14, 2013 at 5:04 PM, Alex Wang <alexw at nicira.com> wrote:

> This commit changes the "ovs-appclt coverage/show" command to show the
> per-second, per-minute and per-hour rates of function invocation. More
> importantly, this makes using coverage counter an easy way to monitor
> the execution of specific functions.
>
> Signed-off-by: Alex Wang <alexw at nicira.com>
>
> ---
>
> v2 -> v3:
> - rebase to current master.
>
> v1 -> v2:
> - abandon the wakeup timer and coverage_wait() function.
> - now the coverage_run() will run only when more than 5 seconds have passed
>   since last run.
>
> ---
>  lib/coverage-unixctl.man |    3 +-
>  lib/coverage.c           |   95
> +++++++++++++++++++++++++++++++++++++++-------
>  lib/coverage.h           |   17 +++++++--
>  lib/timeval.c            |    1 -
>  vswitchd/ovs-vswitchd.c  |    2 +
>  5 files changed, 99 insertions(+), 19 deletions(-)
>
> diff --git a/lib/coverage-unixctl.man b/lib/coverage-unixctl.man
> index 9718894..2d283dc 100644
> --- a/lib/coverage-unixctl.man
> +++ b/lib/coverage-unixctl.man
> @@ -8,4 +8,5 @@ main loop takes unusually long to run.
>  Coverage counters are useful mainly for performance analysis and
>  debugging.
>  .IP "\fBcoverage/show\fR"
> -Displays the values of all of the coverage counters.
> +Displays the per-second, per-minute and per-hour rates, and total count
> +of all of the coverage counters.
> diff --git a/lib/coverage.c b/lib/coverage.c
> index f152474..e3e7610 100644
> --- a/lib/coverage.c
> +++ b/lib/coverage.c
> @@ -47,9 +47,21 @@ struct coverage_counter *coverage_counters[] = {
>  #define n_coverage_counters ARRAY_SIZE(coverage_counters)
>  #endif  /* !USE_LINKER_SECTIONS */
>
> -static unsigned int epoch;
> +/* Makes coverage_run run every 5 seconds. */
> +#define COVERAGE_RUN_INTERVAL    5000
>
Can we drive MIN_LEN from this number? it is hard coded to 12 now, and only
works if the interval is 5 seconds.

> +static long long int coverage_run_time = LLONG_MIN;
> +
> +/* Defines the moving average array index variables. */
> +static unsigned int min_idx = 0;
> +static unsigned int hr_idx = 0;
> +
> +/* Index counter used to compute the moving average array's index. */
> +static unsigned int idx_count = 0;
>
>  static void coverage_read(struct svec *);
> +static unsigned int coverage_array_sum(const unsigned int *arr,
> +                                       const unsigned int len);
> +
>
>  static void
>  coverage_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
> @@ -170,7 +182,7 @@ coverage_log(void)
>          uint32_t hash = coverage_hash();
>          if (coverage_hit(hash)) {
>              VLOG_INFO("Skipping details of duplicate event coverage for "
> -                      "hash=%08"PRIx32" in epoch %u", hash, epoch);
> +                      "hash=%08"PRIx32, hash);
>          } else {
>              struct svec lines;
>              const char *line;
> @@ -189,8 +201,16 @@ coverage_log(void)
>  static void
>  coverage_read_counter(struct svec *lines, const struct coverage_counter
> *c)
>  {
> -    svec_add_nocopy(lines, xasprintf("%-24s %5u / %9llu",
> -                                     c->name, c->count, c->count +
> c->total));
> +    /* The per second rate is calculated via averaging the counts in
> +     * last 5-second interval. */
> +    svec_add_nocopy(lines,
> +            xasprintf("%-24s %5.1f/sec %7u/min "
> +                      "%9u/hr   total: %llu",
> +                      c->name,
> +                      c->sec_to_min[(min_idx + 11) % MIN_LEN] / 5.0

How about use (MIN_LEN -1) instead of 11?
 +                      coverage_array_sum(c->sec_to_min, MIN_LEN),

> +                      coverage_array_sum(c->min_to_hr,  HR_LEN),
> +                      c->count + c->total));
>  }
>
>  /* Adds coverage counter information to 'lines'. */
> @@ -204,8 +224,8 @@ coverage_read(struct svec *lines)
>      hash = coverage_hash();
>
>      n_never_hit = 0;
> -    svec_add_nocopy(lines, xasprintf("Event coverage (epoch %u/entire
> run), "
> -                                     "hash=%08"PRIx32":", epoch, hash));
> +    svec_add_nocopy(lines, xasprintf("Event coverage (frequency), "
> +                                     "hash=%08"PRIx32":", hash));
>      for (i = 0; i < n_coverage_counters; i++) {
>          struct coverage_counter *c = coverage_counters[i];
>          if (c->count) {
> @@ -225,16 +245,65 @@ coverage_read(struct svec *lines)
>      svec_add_nocopy(lines, xasprintf("%zu events never hit",
> n_never_hit));
>  }
>
> -/* Advances to the next epoch of coverage, resetting all the counters to
> 0. */
> +/* Runs every second to update the coverage counters'
>
Every 5 seconds?

> + * sec_to_min array and min_to_hr array. */
>  void
> -coverage_clear(void)
> +coverage_run(void)
>  {
> +    long long int cur_time = time_msec();
> +
> +    /* Initialize the coverage_run_time. */
> +    if (coverage_run_time == LLONG_MIN) {
> +        coverage_run_time = time_msec();
> +    }
> +
> +    if (cur_time >= coverage_run_time) {
> +        size_t i, j;
> +        /* Computes the number of 5-second slots. */
> +        int slots = (cur_time - coverage_run_time) / COVERAGE_RUN_INTERVAL
> +                    + 1;
> +
> +        /* This loop is necessary, since it is possible that the actual
> +         * run interval is multiple of 5 seconds. */
> +        for (i = 0; i < slots; i++) {
> +            /* Updates the index variables. */
> +            /* The min_idx is increased from 0 to 11. Every time the
> +             * min_idx finishes a cycle (a cycle is one minute),
> +             * the hr_idx is incremented by 1. */
> +            min_idx = idx_count % MIN_LEN;
> +            hr_idx  = idx_count / MIN_LEN;
> +
> +            for (j = 0; j < n_coverage_counters; j++) {
> +                struct coverage_counter *c = coverage_counters[j];
> +                /* Calculates the portion to be added, which is the
> average
> +                 * of counts over the time. Note, the last loop will also
> +                 * include the remainder. */
>
It would be nice to add comments about what the following logic is trying
to accomplish.

> +                int portion = c->count / slots + (i == slots - 1 ?
> +                              c->count % slots : 0);
> +
> +                c->total += portion;
> +                c->count = (i == slots -1 ? 0 : c->count) ;
> +                c->sec_to_min[min_idx] = portion;
> +                /* Note, only adds up the latest count portion here. */
> +                c->min_to_hr[hr_idx] = min_idx == 0 ?
> +                     portion : (c->min_to_hr[hr_idx] + portion);
> +            }
> +            /* This is to guarantee that mov_avg_hr_idx ranges from 0 to
> 59. */
> +            idx_count = (idx_count + 1) % 720;
>
How about MIN_LEN * HR_LEN instead of 720.

> +            /* Updates the run time. */
> +            coverage_run_time += COVERAGE_RUN_INTERVAL;
> +        }
> +    }
> +}
> +
> +static unsigned int
> +coverage_array_sum(const unsigned int *arr, const unsigned int len)
> +{
> +    unsigned int sum = 0;
>      size_t i;
>
> -    epoch++;
> -    for (i = 0; i < n_coverage_counters; i++) {
> -        struct coverage_counter *c = coverage_counters[i];
> -        c->total += c->count;
> -        c->count = 0;
> +    for (i = 0; i < len; i++) {
> +        sum += arr[i];
>      }
> +    return sum;
>  }
> diff --git a/lib/coverage.h b/lib/coverage.h
> index 968c489..26837ed 100644
> --- a/lib/coverage.h
> +++ b/lib/coverage.h
> @@ -29,11 +29,19 @@
>
>  #include "vlog.h"
>
> +/* Defines the moving average array length. */
> +#define MIN_LEN 12   /* 12 * 5 seconds = 1 minute */
>
Would be nice to derive the number using  COVERAGE_RUN_INTERVAL. So that it
will be easier to change interval later on.

> +#define HR_LEN  60   /* 60 * 1 minute = 1 hour */
> +
>  /* A coverage counter. */
>  struct coverage_counter {
>      const char *name;           /* Textual name. */
> -    unsigned int count;         /* Count within the current epoch. */
> -    unsigned long long int total; /* Total count over all epochs. */
> +    unsigned int count;         /* Count within the current second. */
> +    unsigned long long int total; /* Total count over all time. */
> +
> +    /* The moving average arrays. */
> +    unsigned int sec_to_min[MIN_LEN];
> +    unsigned int min_to_hr[HR_LEN];
>  };
>
>  /* Defines COUNTER.  There must be exactly one such definition at file
> scope
> @@ -57,11 +65,12 @@ struct coverage_counter {
>
>  void coverage_init(void);
>  void coverage_log(void);
> -void coverage_clear(void);
> +void coverage_run(void);
>
>  /* Implementation detail. */
>  #define COVERAGE_DEFINE__(COUNTER)                              \
>          extern struct coverage_counter counter_##COUNTER;       \
> -        struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0 }
> +        struct coverage_counter counter_##COUNTER = { #COUNTER, 0, 0, \
> +                                                      {0}, {0} }
>
>  #endif /* coverage.h */
> diff --git a/lib/timeval.c b/lib/timeval.c
> index faf8e7b..2380a0a 100644
> --- a/lib/timeval.c
> +++ b/lib/timeval.c
> @@ -304,7 +304,6 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long
> long int timeout_when,
>      if (*last_wakeup) {
>          log_poll_interval(*last_wakeup);
>      }
> -    coverage_clear();
>      start = time_msec();
>      blocked = false;
>
> diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c
> index bc45dac..a9db1fd 100644
> --- a/vswitchd/ovs-vswitchd.c
> +++ b/vswitchd/ovs-vswitchd.c
> @@ -28,6 +28,7 @@
>  #include "bridge.h"
>  #include "command-line.h"
>  #include "compiler.h"
> +#include "coverage.h"
>  #include "daemon.h"
>  #include "dirs.h"
>  #include "dpif.h"
> @@ -119,6 +120,7 @@ main(int argc, char *argv[])
>          bridge_run_fast();
>          unixctl_server_run(unixctl);
>          netdev_run();
> +        coverage_run();
>
>          signal_wait(sighup);
>          memory_wait();
> --
> 1.7.9.5
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20130815/22124637/attachment-0003.html>


More information about the dev mailing list