Message ID | 1531132151-2321-1-git-send-email-vladbu@mellanox.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | [net-next] net: sched: refactor flower walk to iterate over idr | expand |
On Mon, Jul 09, 2018 at 01:29:11PM +0300, Vlad Buslov wrote: > Extend struct tcf_walker with additional 'cookie' field. It is intended to > be used by classifier walk implementations to continue iteration directly > from particular filter, instead of iterating 'skip' number of times. > > Change flower walk implementation to save filter handle in 'cookie'. Each > time flower walk is called, it looks up filter with saved handle directly > with idr, instead of iterating over filter linked list 'skip' number of > times. This change improves complexity of dumping flower classifier from > quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) > > Reviewed-by: Jiri Pirko <jiri@mellanox.com> > Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Reported-by: Simon Horman <simon.horman@netronome.com> Thanks, I'm very pleased to see this change. I would appreciate it if we could have a little time to test its impact on performance thoroughly. One question: will this work as expected (i.e. be at least backwards compatible) with existing user-space code?
On Tue 10 Jul 2018 at 13:55, Simon Horman <simon.horman@netronome.com> wrote: > On Mon, Jul 09, 2018 at 01:29:11PM +0300, Vlad Buslov wrote: >> Extend struct tcf_walker with additional 'cookie' field. It is intended to >> be used by classifier walk implementations to continue iteration directly >> from particular filter, instead of iterating 'skip' number of times. >> >> Change flower walk implementation to save filter handle in 'cookie'. Each >> time flower walk is called, it looks up filter with saved handle directly >> with idr, instead of iterating over filter linked list 'skip' number of >> times. This change improves complexity of dumping flower classifier from >> quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) >> >> Reviewed-by: Jiri Pirko <jiri@mellanox.com> >> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> > > Reported-by: Simon Horman <simon.horman@netronome.com> > > Thanks, I'm very pleased to see this change. I would appreciate it if > we could have a little time to test its impact on performance > thoroughly. For me it reduced time needed to dump 5m flows to ~50 seconds. Not a very thorough benchmark, but performance improvement was so dramatic that I decided to not investigate further. > > One question: will this work as expected (i.e. be at least backwards > compatible) with existing user-space code? I considered that and didn't find any reason why it would break compatibility. Basically with current flower flows are dumped in arbitrary order, and with this change dump(accidentally) outputs flows in sorted ascending order. User space shouldn't expect any ordering in dumped flows anyway, right?
On Tue, Jul 10, 2018 at 08:02:10PM +0300, Vlad Buslov wrote: > > On Tue 10 Jul 2018 at 13:55, Simon Horman <simon.horman@netronome.com> wrote: > > On Mon, Jul 09, 2018 at 01:29:11PM +0300, Vlad Buslov wrote: > >> Extend struct tcf_walker with additional 'cookie' field. It is intended to > >> be used by classifier walk implementations to continue iteration directly > >> from particular filter, instead of iterating 'skip' number of times. > >> > >> Change flower walk implementation to save filter handle in 'cookie'. Each > >> time flower walk is called, it looks up filter with saved handle directly > >> with idr, instead of iterating over filter linked list 'skip' number of > >> times. This change improves complexity of dumping flower classifier from > >> quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) > >> > >> Reviewed-by: Jiri Pirko <jiri@mellanox.com> > >> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> > > > > Reported-by: Simon Horman <simon.horman@netronome.com> > > > > Thanks, I'm very pleased to see this change. I would appreciate it if > > we could have a little time to test its impact on performance > > thoroughly. > > For me it reduced time needed to dump 5m flows to ~50 seconds. Not a > very thorough benchmark, but performance improvement was so dramatic > that I decided to not investigate further. Thanks, we have also now measured a similar improvement in performance. > > One question: will this work as expected (i.e. be at least backwards > > compatible) with existing user-space code? > > I considered that and didn't find any reason why it would break > compatibility. Basically with current flower flows are dumped in > arbitrary order, and with this change dump(accidentally) outputs flows > in sorted ascending order. User space shouldn't expect any ordering in > dumped flows anyway, right? Agreed. I don't think we need to be worried about changes in the order of dumped flows. Reviewed-by: Simon Horman <simon.horman@netronome.com>
From: Vlad Buslov <vladbu@mellanox.com> Date: Mon, 9 Jul 2018 13:29:11 +0300 > Extend struct tcf_walker with additional 'cookie' field. It is intended to > be used by classifier walk implementations to continue iteration directly > from particular filter, instead of iterating 'skip' number of times. > > Change flower walk implementation to save filter handle in 'cookie'. Each > time flower walk is called, it looks up filter with saved handle directly > with idr, instead of iterating over filter linked list 'skip' number of > times. This change improves complexity of dumping flower classifier from > quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) > > Reviewed-by: Jiri Pirko <jiri@mellanox.com> > Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Applied, thank you.
On Tue, Jul 10, 2018 at 8:02 PM, Vlad Buslov <vladbu@mellanox.com> wrote: > > On Tue 10 Jul 2018 at 13:55, Simon Horman <simon.horman@netronome.com> wrote: >> On Mon, Jul 09, 2018 at 01:29:11PM +0300, Vlad Buslov wrote: >>> Extend struct tcf_walker with additional 'cookie' field. It is intended to >>> be used by classifier walk implementations to continue iteration directly >>> from particular filter, instead of iterating 'skip' number of times. >>> >>> Change flower walk implementation to save filter handle in 'cookie'. Each >>> time flower walk is called, it looks up filter with saved handle directly >>> with idr, instead of iterating over filter linked list 'skip' number of >>> times. This change improves complexity of dumping flower classifier from >>> quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) >>> >>> Reviewed-by: Jiri Pirko <jiri@mellanox.com> >>> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> >> >> Reported-by: Simon Horman <simon.horman@netronome.com> >> >> Thanks, I'm very pleased to see this change. I would appreciate it if >> we could have a little time to test its impact on performance >> thoroughly. > > For me it reduced time needed to dump 5m flows to ~50 seconds. Not a > very thorough benchmark, but performance improvement was so dramatic > that I decided to not investigate further. down from how long to 50 seconds??
On Sat 14 Jul 2018 at 15:50, Or Gerlitz <gerlitz.or@gmail.com> wrote: > On Tue, Jul 10, 2018 at 8:02 PM, Vlad Buslov <vladbu@mellanox.com> wrote: >> >> On Tue 10 Jul 2018 at 13:55, Simon Horman <simon.horman@netronome.com> wrote: >>> On Mon, Jul 09, 2018 at 01:29:11PM +0300, Vlad Buslov wrote: >>>> Extend struct tcf_walker with additional 'cookie' field. It is intended to >>>> be used by classifier walk implementations to continue iteration directly >>>> from particular filter, instead of iterating 'skip' number of times. >>>> >>>> Change flower walk implementation to save filter handle in 'cookie'. Each >>>> time flower walk is called, it looks up filter with saved handle directly >>>> with idr, instead of iterating over filter linked list 'skip' number of >>>> times. This change improves complexity of dumping flower classifier from >>>> quadratic to linearithmic. (assuming idr lookup has logarithmic complexity) >>>> >>>> Reviewed-by: Jiri Pirko <jiri@mellanox.com> >>>> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> >>> >>> Reported-by: Simon Horman <simon.horman@netronome.com> >>> >>> Thanks, I'm very pleased to see this change. I would appreciate it if >>> we could have a little time to test its impact on performance >>> thoroughly. >> >> For me it reduced time needed to dump 5m flows to ~50 seconds. Not a >> very thorough benchmark, but performance improvement was so dramatic >> that I decided to not investigate further. > > > down from how long to 50 seconds?? From this: gact$ time sudo tc -s filter show dev eth0_0 ingress | grep in_hw | wc -l 5000000 real 2099m29.689s user 0m42.036s sys 2098m55.680s
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index a3c1a2c47cd4..ff7708c40e22 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -13,6 +13,7 @@ struct tcf_walker { int stop; int skip; int count; + unsigned long cookie; int (*fn)(struct tcf_proto *, void *node, struct tcf_walker *); }; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index cdc3c87c53e6..9aa70e2035dc 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1463,7 +1463,9 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent, arg.w.stop = 0; arg.w.skip = cb->args[1] - 1; arg.w.count = 0; + arg.w.cookie = cb->args[2]; tp->ops->walk(tp, &arg.w); + cb->args[2] = arg.w.cookie; cb->args[1] = arg.w.count + 1; if (arg.w.stop) return false; diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 2b5be42a9f1c..754def20b432 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -1058,19 +1058,17 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg) { struct cls_fl_head *head = rtnl_dereference(tp->root); struct cls_fl_filter *f; - struct fl_flow_mask *mask; - list_for_each_entry_rcu(mask, &head->masks, list) { - list_for_each_entry_rcu(f, &mask->filters, list) { - if (arg->count < arg->skip) - goto skip; - if (arg->fn(tp, f, arg) < 0) { - arg->stop = 1; - break; - } -skip: - arg->count++; + arg->count = arg->skip; + + while ((f = idr_get_next_ul(&head->handle_idr, + &arg->cookie)) != NULL) { + if (arg->fn(tp, f, arg) < 0) { + arg->stop = 1; + break; } + arg->cookie = f->handle + 1; + arg->count++; } }