Thanks Keith and Justin, I applied this to master and branch-2.0.
On Tue, Sep 24, 2013 at 02:33:53PM -0700, Justin Pettit wrote: > Acked-by: Justin Pettit <jpet...@nicira.com> > > > On Sep 24, 2013, at 10:17 AM, Ben Pfaff <b...@nicira.com> wrote: > > > The hmap code has for a long time incremented a counter when a hash bucket > > grew to have many entries. This can let a developer know that some hash > > function is performing poorly, but doesn't give any hint as to which one. > > This commit improves the situation by adding rate-limited debug logging > > that points out a particular line of code as the source of the poor hash > > behavior. It should make issues easier to track down. > > > > Bug #19926. > > CC: Keith Amidon <ke...@nicira.com> > > Signed-off-by: Ben Pfaff <b...@nicira.com> > > --- > > lib/hmap.c | 38 ++++++++++++++++++++++++++++---------- > > lib/hmap.h | 31 +++++++++++++++++++++++-------- > > 2 files changed, 51 insertions(+), 18 deletions(-) > > > > diff --git a/lib/hmap.c b/lib/hmap.c > > index f15e72c..a559a77 100644 > > --- a/lib/hmap.c > > +++ b/lib/hmap.c > > @@ -21,6 +21,9 @@ > > #include "coverage.h" > > #include "random.h" > > #include "util.h" > > +#include "vlog.h" > > + > > +VLOG_DEFINE_THIS_MODULE(hmap); > > > > COVERAGE_DEFINE(hmap_pathological); > > COVERAGE_DEFINE(hmap_expand); > > @@ -85,7 +88,7 @@ hmap_moved(struct hmap *hmap) > > } > > > > static void > > -resize(struct hmap *hmap, size_t new_mask) > > +resize(struct hmap *hmap, size_t new_mask, const char *where) > > { > > struct hmap tmp; > > size_t i; > > @@ -109,7 +112,10 @@ resize(struct hmap *hmap, size_t new_mask) > > count++; > > } > > if (count > 5) { > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, > > 10); > > COVERAGE_INC(hmap_pathological); > > + VLOG_DBG_RL(&rl, "%s: %d nodes in bucket (%zu nodes, %zu > > buckets)", > > + where, count, hmap->n, hmap->mask + 1); > > } > > } > > hmap_swap(hmap, &tmp); > > @@ -136,38 +142,50 @@ calc_mask(size_t capacity) > > return mask; > > } > > > > -/* Expands 'hmap', if necessary, to optimize the performance of searches. > > */ > > +/* Expands 'hmap', if necessary, to optimize the performance of searches. > > + * > > + * ('where' is used in debug logging. Commonly one would use > > hmap_expand() to > > + * automatically provide the caller's source file and line number for > > + * 'where'.) */ > > void > > -hmap_expand(struct hmap *hmap) > > +hmap_expand_at(struct hmap *hmap, const char *where) > > { > > size_t new_mask = calc_mask(hmap->n); > > if (new_mask > hmap->mask) { > > COVERAGE_INC(hmap_expand); > > - resize(hmap, new_mask); > > + resize(hmap, new_mask, where); > > } > > } > > > > -/* Shrinks 'hmap', if necessary, to optimize the performance of iteration. > > */ > > +/* Shrinks 'hmap', if necessary, to optimize the performance of iteration. > > + * > > + * ('where' is used in debug logging. Commonly one would use > > hmap_shrink() to > > + * automatically provide the caller's source file and line number for > > + * 'where'.) */ > > void > > -hmap_shrink(struct hmap *hmap) > > +hmap_shrink_at(struct hmap *hmap, const char *where) > > { > > size_t new_mask = calc_mask(hmap->n); > > if (new_mask < hmap->mask) { > > COVERAGE_INC(hmap_shrink); > > - resize(hmap, new_mask); > > + resize(hmap, new_mask, where); > > } > > } > > > > /* Expands 'hmap', if necessary, to optimize the performance of searches > > when > > * it has up to 'n' elements. (But iteration will be slow in a hash map > > whose > > - * allocated capacity is much higher than its current number of nodes.) */ > > + * allocated capacity is much higher than its current number of nodes.) > > + * > > + * ('where' is used in debug logging. Commonly one would use > > hmap_reserve() to > > + * automatically provide the caller's source file and line number for > > + * 'where'.) */ > > void > > -hmap_reserve(struct hmap *hmap, size_t n) > > +hmap_reserve_at(struct hmap *hmap, size_t n, const char *where) > > { > > size_t new_mask = calc_mask(n); > > if (new_mask > hmap->mask) { > > COVERAGE_INC(hmap_reserve); > > - resize(hmap, new_mask); > > + resize(hmap, new_mask, where); > > } > > } > > > > diff --git a/lib/hmap.h b/lib/hmap.h > > index ab7d3ae..76a73ac 100644 > > --- a/lib/hmap.h > > +++ b/lib/hmap.h > > @@ -1,5 +1,5 @@ > > /* > > - * Copyright (c) 2008, 2009, 2010, 2012 Nicira, Inc. > > + * Copyright (c) 2008, 2009, 2010, 2012, 2013 Nicira, Inc. > > * > > * Licensed under the Apache License, Version 2.0 (the "License"); > > * you may not use this file except in compliance with the License. > > @@ -78,14 +78,24 @@ static inline size_t hmap_count(const struct hmap *); > > static inline bool hmap_is_empty(const struct hmap *); > > > > /* Adjusting capacity. */ > > -void hmap_expand(struct hmap *); > > -void hmap_shrink(struct hmap *); > > -void hmap_reserve(struct hmap *, size_t capacity); > > +void hmap_expand_at(struct hmap *, const char *where); > > +#define hmap_expand(HMAP) hmap_expand_at(HMAP, SOURCE_LOCATOR) > > + > > +void hmap_shrink_at(struct hmap *, const char *where); > > +#define hmap_shrink(HMAP) hmap_shrink_at(HMAP, SOURCE_LOCATOR) > > + > > +void hmap_reserve_at(struct hmap *, size_t capacity, const char *where); > > +#define hmap_reserve(HMAP, CAPACITY) \ > > + hmap_reserve_at(HMAP, CAPACITY, SOURCE_LOCATOR) > > > > /* Insertion and deletion. */ > > +static inline void hmap_insert_at(struct hmap *, struct hmap_node *, > > + size_t hash, const char *where); > > +#define hmap_insert(HMAP, NODE, HASH) \ > > + hmap_insert_at(HMAP, NODE, HASH, SOURCE_LOCATOR) > > + > > static inline void hmap_insert_fast(struct hmap *, > > struct hmap_node *, size_t hash); > > -static inline void hmap_insert(struct hmap *, struct hmap_node *, size_t > > hash); > > static inline void hmap_remove(struct hmap *, struct hmap_node *); > > > > void hmap_node_moved(struct hmap *, struct hmap_node *, struct hmap_node *); > > @@ -199,13 +209,18 @@ hmap_insert_fast(struct hmap *hmap, struct hmap_node > > *node, size_t hash) > > } > > > > /* Inserts 'node', with the given 'hash', into 'hmap', and expands 'hmap' if > > - * necessary to optimize search performance. */ > > + * necessary to optimize search performance. > > + * > > + * ('where' is used in debug logging. Commonly one would use > > hmap_insert() to > > + * automatically provide the caller's source file and line number for > > + * 'where'.) */ > > static inline void > > -hmap_insert(struct hmap *hmap, struct hmap_node *node, size_t hash) > > +hmap_insert_at(struct hmap *hmap, struct hmap_node *node, size_t hash, > > + const char *where) > > { > > hmap_insert_fast(hmap, node, hash); > > if (hmap->n / 2 > hmap->mask) { > > - hmap_expand(hmap); > > + hmap_expand_at(hmap, where); > > } > > } > > > > -- > > 1.7.10.4 > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev