From 934396731734b3e5ae842936fd23f83f15f29c53 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 13 May 2022 13:56:53 -0700 Subject: [PATCH] wgengine/filter: preallocate some hot slices in MatchesFromFilterRules (#4672) Profiling identified this as a fairly hot path for growing a slice. Given this is only used in control & when a new packet filter is received, this shouldnt be hot in the client. --- wgengine/filter/filter_test.go | 9 +++++++-- wgengine/filter/tailcfg.go | 9 ++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/wgengine/filter/filter_test.go b/wgengine/filter/filter_test.go index 00826714b..55fd98554 100644 --- a/wgengine/filter/filter_test.go +++ b/wgengine/filter/filter_test.go @@ -780,6 +780,7 @@ func TestMatchesFromFilterRules(t *testing.T) { Srcs: []netaddr.IPPrefix{ netaddr.MustParseIPPrefix("100.64.1.1/32"), }, + Caps: []CapMatch{}, }, }, }, @@ -809,6 +810,7 @@ func TestMatchesFromFilterRules(t *testing.T) { Srcs: []netaddr.IPPrefix{ netaddr.MustParseIPPrefix("100.64.1.1/32"), }, + Caps: []CapMatch{}, }, }, }, @@ -819,8 +821,11 @@ func TestMatchesFromFilterRules(t *testing.T) { if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("wrong\n got: %v\nwant: %v\n", got, tt.want) + + compareIP := cmp.Comparer(func(a, b netaddr.IP) bool { return a == b }) + compareIPPrefix := cmp.Comparer(func(a, b netaddr.IPPrefix) bool { return a == b }) + if diff := cmp.Diff(got, tt.want, compareIP, compareIPPrefix); diff != "" { + t.Errorf("wrong (-got+want)\n%s", diff) } }) } diff --git a/wgengine/filter/tailcfg.go b/wgengine/filter/tailcfg.go index 799fbf21a..d5f63dbd1 100644 --- a/wgengine/filter/tailcfg.go +++ b/wgengine/filter/tailcfg.go @@ -28,7 +28,14 @@ func MatchesFromFilterRules(pf []tailcfg.FilterRule) ([]Match, error) { var erracc error for _, r := range pf { - m := Match{} + // Profiling determined that this function was spending a lot + // of time in runtime.growslice. As such, we attempt to + // pre-allocate some slices. Multipliers were chosen arbitrarily. + m := Match{ + Srcs: make([]netaddr.IPPrefix, 0, len(r.SrcIPs)), + Dsts: make([]NetPortRange, 0, 2*len(r.DstPorts)), + Caps: make([]CapMatch, 0, 3*len(r.CapGrant)), + } if len(r.IPProto) == 0 { m.IPProto = append([]ipproto.Proto(nil), defaultProtos...)