As the number of flows grows so does the length of time taken to update the statistics of all facets. It has been obvserved that this becomes a performance problem. This patch mitiages this effect by only dumping a limited number of facets at a time.
Signed-off-by: Simon Horman <ho...@verge.net.au> --- Since the last time that I tested this code (changest 279320b8276011df3667478de6750d5a40d0c6eb, "rhel: Add ability to enable bridge compatibility mode in /etc/sysconfig/openvswitch") it seems that the cost of dumping statistics has increased. I suspect that this relates to the introducation of subfacet_find(). In any case I believe that a higher cost of dumping stats makes a stronger case for the change introduced in this patch. The previously posted version of this patch used a limit of 100,000 facets per statistics dump. This revision uses a limit of 20,000 subfacets per dump. Empirically these two revisions appear to exhibit the same performance. --- ofproto/ofproto-dpif.c | 28 ++++++++++++++++++++++------ 1 files changed, 22 insertions(+), 6 deletions(-) diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index ea5ed1e..e2a3939 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -345,6 +345,7 @@ struct subfacet { /* Owners. */ struct hmap_node hmap_node; /* In struct ofproto_dpif 'subfacets' list. */ struct list list_node; /* In struct facet's 'facets' list. */ + struct list may_expire; /* Potential expiry list. */ struct facet *facet; /* Owning facet. */ /* Key. @@ -507,6 +508,7 @@ struct ofproto_dpif { /* Facets. */ struct hmap facets; struct hmap subfacets; + struct list expirable_subfacets; /* Revalidation. */ struct table_dpif tables[N_TABLES]; @@ -659,6 +661,7 @@ construct(struct ofproto *ofproto_, int *n_tablesp) hmap_init(&ofproto->facets); hmap_init(&ofproto->subfacets); + list_init(&ofproto->expirable_subfacets); for (i = 0; i < N_TABLES; i++) { struct table_dpif *table = &ofproto->tables[i]; @@ -2916,12 +2919,18 @@ static void update_stats(struct ofproto_dpif *p) { const struct dpif_flow_stats *stats; - struct dpif_flow_dump dump; + static struct dpif_flow_dump dump; const struct nlattr *key; size_t key_len; + static bool complete = true; + int count = 20000; - dpif_flow_dump_start(&dump, p->dpif); - while (dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) { + if (complete) { + dpif_flow_dump_start(&dump, p->dpif); + complete = false; + } + while (--count && + dpif_flow_dump_next(&dump, &key, &key_len, NULL, NULL, &stats)) { struct subfacet *subfacet; subfacet = subfacet_find(p, key, key_len); @@ -2944,6 +2953,7 @@ update_stats(struct ofproto_dpif *p) subfacet->dp_packet_count = stats->n_packets; subfacet->dp_byte_count = stats->n_bytes; + list_insert(&p->expirable_subfacets, &subfacet->may_expire); subfacet_update_time(subfacet, stats->used); facet_account(facet); facet_push_stats(facet); @@ -2963,7 +2973,10 @@ update_stats(struct ofproto_dpif *p) dpif_flow_del(p->dpif, key, key_len, NULL); } } - dpif_flow_dump_done(&dump); + if (count) { + dpif_flow_dump_done(&dump); + complete = true; + } } /* Calculates and returns the number of milliseconds of idle time after which @@ -3060,11 +3073,12 @@ expire_subfacets(struct ofproto_dpif *ofproto, int dp_max_idle) long long int cutoff = time_msec() - dp_max_idle; struct subfacet *subfacet, *next_subfacet; - HMAP_FOR_EACH_SAFE (subfacet, next_subfacet, hmap_node, - &ofproto->subfacets) { + LIST_FOR_EACH_SAFE (subfacet, next_subfacet, may_expire, + &ofproto->expirable_subfacets) { if (subfacet->used < cutoff) { subfacet_destroy(subfacet); } + list_remove(&subfacet->may_expire); } } @@ -3739,6 +3753,7 @@ subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, subfacet = xzalloc(sizeof *subfacet); hmap_insert(&ofproto->subfacets, &subfacet->hmap_node, key_hash); list_push_back(&facet->subfacets, &subfacet->list_node); + list_init(&subfacet->may_expire); subfacet->facet = facet; subfacet->used = time_msec(); subfacet->key_fitness = key_fitness; @@ -3780,6 +3795,7 @@ subfacet_destroy__(struct subfacet *subfacet) subfacet_uninstall(subfacet); hmap_remove(&ofproto->subfacets, &subfacet->hmap_node); + list_remove(&subfacet->may_expire); list_remove(&subfacet->list_node); free(subfacet->key); free(subfacet->actions); -- 1.7.4.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev