The instant_stats_could_have_changed variable seems a bit of a kludge to
me.  It seems it would be cleaner if instant_stats_run() maintained the
idl_seqno at the time of the 'instant_txn' creation.  If that sequence
number is out of date, we know we need to wait until instant_next_txn.
 Thoughts?

Ethan


On Tue, Mar 19, 2013 at 2:04 PM, Ben Pfaff <b...@nicira.com> wrote:

> Some information in the database must be kept as up-to-date as
> possible to allow controllers to respond rapidly to network outages.
> We call these statistics "instant" stats.
>
> Until now, the instant stats have been updated on every trip through
> the main loop.  This work scales with the number of interfaces that
> ovs-vswitchd manages.  With CFM enabled on 5000 interfaces, even with
> a low transmission rate, we see ovs-vswitchd using 100% CPU just to
> maintain statistics, even with no actual changes.
>
> This commit rate-limits updates to instant stats to at most 10 times
> per second.  Earlier tests I did with similar patches showed a major
> reduction in CPU usage.  I have not rerun those tests with this patch,
> but I expect that the CPU usage should similarly decline.
>
> CC: Ram Jothikumar <rjothiku...@nicira.com>
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> ---
>  vswitchd/bridge.c |   75
> +++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 files changed, 67 insertions(+), 8 deletions(-)
>
> diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
> index 9449879..6dc3db2 100644
> --- a/vswitchd/bridge.c
> +++ b/vswitchd/bridge.c
> @@ -2019,17 +2019,61 @@ refresh_controller_status(void)
>
>      ofproto_free_ofproto_controller_info(&info);
>  }
> +
> +/* "Instant" stats.
> + *
> + * Some information in the database must be kept as up-to-date as
> possible to
> + * allow controllers to respond rapidly to network outages.  We call these
> + * statistics "instant" stats.
> + *
> + * We wish to update these statistics every INSTANT_INTERVAL_MSEC
> milliseconds,
> + * assuming that they've changed.  The only means we have to determine
> whether
> + * they have changed are:
> + *
> + *   - Try to commit changes to the database.  If nothing changed, then
> + *     ovsdb_idl_txn_commit() returns TXN_UNCHANGED, otherwise some other
> + *     value.
> + *
> + *   - instant_stats_run() is called late in the run loop, after anything
> that
> + *     might change any of the instant stats.
> + *
> + * We use these two facts together to avoid waking the process up every
> + * INSTANT_INTERVAL_MSEC whether there is any change or not.
> + */
> +
> +/* Minimum interval between writing updates to the instant stats to the
> + * database. */
> +#define INSTANT_INTERVAL_MSEC 100
> +
> +/* Current instant stats database transaction, NULL if there is no ongoing
> + * transaction. */
> +static struct ovsdb_idl_txn *instant_txn;
> +
> +/* Next time (in msec on monotonic clock) at which we will update the
> instant
> + * stats.  */
> +static long long int instant_next_txn = LLONG_MIN;
> +
> +/* True if the run loop has run since we last saw that the instant stats
> were
> + * unchanged, that is, this is true if we need to wake up at
> 'instant_next_txn'
> + * to refresh the instant stats. */
> +static bool instant_stats_could_have_changed;
>
>  static void
> -refresh_instant_stats(void)
> +instant_stats_run(void)
>  {
> -    static struct ovsdb_idl_txn *txn = NULL;
> +    enum ovsdb_idl_txn_status status;
>
> -    if (!txn) {
> +    instant_stats_could_have_changed = true;
> +
> +    if (!instant_txn) {
>          struct bridge *br;
>
> -        txn = ovsdb_idl_txn_create(idl);
> +        if (time_msec() < instant_next_txn) {
> +            return;
> +        }
> +        instant_next_txn = time_msec() + INSTANT_INTERVAL_MSEC;
>
> +        instant_txn = ovsdb_idl_txn_create(idl);
>          HMAP_FOR_EACH (br, node, &all_bridges) {
>              struct iface *iface;
>              struct port *port;
> @@ -2078,12 +2122,26 @@ refresh_instant_stats(void)
>          }
>      }
>
> -    if (ovsdb_idl_txn_commit(txn) != TXN_INCOMPLETE) {
> -        ovsdb_idl_txn_destroy(txn);
> -        txn = NULL;
> +    status = ovsdb_idl_txn_commit(instant_txn);
> +    if (status != TXN_INCOMPLETE) {
> +        ovsdb_idl_txn_destroy(instant_txn);
> +        instant_txn = NULL;
> +    }
> +    if (status == TXN_UNCHANGED) {
> +        instant_stats_could_have_changed = false;
>      }
>  }
>
> +static void
> +instant_stats_wait(void)
> +{
> +    if (instant_txn) {
> +        ovsdb_idl_txn_wait(instant_txn);
> +    } else if (instant_stats_could_have_changed) {
> +        poll_timer_wait_until(instant_next_txn);
> +    }
> +}
> +
>  /* Performs periodic activity required by bridges that needs to be done
> with
>   * the least possible latency.
>   *
> @@ -2254,7 +2312,7 @@ bridge_run(void)
>      }
>
>      run_system_stats();
> -    refresh_instant_stats();
> +    instant_stats_run();
>  }
>
>  void
> @@ -2286,6 +2344,7 @@ bridge_wait(void)
>      }
>
>      system_stats_wait();
> +    instant_stats_wait();
>  }
>
>  /* Adds some memory usage statistics for bridges into 'usage', for use
> with
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to