From 020e904f4e2c08f942eb39f22af6a85d9805d19d Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 18 May 2021 09:07:11 -0700 Subject: [PATCH] internal/deephash: add special handling for netaddr.IPPort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The acyclic map code interacts badly with netaddr.IPs. One of the netaddr.IP fields is an *intern.Value, and we use a few sentinel values. Those sentinel values make many of the netaddr data structures appear cyclic. One option would be to replace the cycle-detection code with a Floyd-Warshall style algorithm. The downside is that this will take longer to detect cycles, particularly if the cycle is long. This problem is exacerbated by the fact that the acyclic cycle detection code shares a single visited map for the entire data structure, not just the subsection of the data structure localized to the map. Unfortunately, the extra allocations and work (and code) to use per-map visited maps make this option not viable. Instead, continue to special-case netaddr data types. name old time/op new time/op delta Hash-8 22.4µs ± 0% 14.0µs ± 0% -37.59% (p=0.008 n=5+5) HashMapAcyclic-8 23.8µs ± 0% 24.3µs ± 1% +1.75% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Hash-8 2.49kB ± 0% 2.16kB ± 0% ~ (p=0.079 n=4+5) HashMapAcyclic-8 2.53kB ± 0% 2.53kB ± 0% ~ (all equal) name old allocs/op new allocs/op delta Hash-8 86.0 ± 0% 77.0 ± 0% -10.47% (p=0.008 n=5+5) HashMapAcyclic-8 202 ± 0% 202 ± 0% ~ (all equal) Signed-off-by: Josh Bleecher Snyder --- internal/deephash/deephash.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/deephash/deephash.go b/internal/deephash/deephash.go index d1a5a8687..8706c199f 100644 --- a/internal/deephash/deephash.go +++ b/internal/deephash/deephash.go @@ -45,6 +45,7 @@ func Print(w *bufio.Writer, v ...interface{}) { var ( netaddrIPType = reflect.TypeOf(netaddr.IP{}) netaddrIPPrefix = reflect.TypeOf(netaddr.IPPrefix{}) + netaddrIPPort = reflect.TypeOf(netaddr.IPPort{}) wgkeyKeyType = reflect.TypeOf(wgkey.Key{}) wgkeyPrivateType = reflect.TypeOf(wgkey.Private{}) tailcfgDiscoKeyType = reflect.TypeOf(tailcfg.DiscoKey{}) @@ -88,6 +89,20 @@ func print(w *bufio.Writer, v reflect.Value, visited map[uintptr]bool) (acyclic w.Write(b) return true } + case netaddrIPPort: + var b []byte + var err error + if v.CanAddr() { + x := v.Addr().Interface().(*netaddr.IPPort) + b, err = x.MarshalText() + } else { + x := v.Interface().(netaddr.IPPort) + b, err = x.MarshalText() + } + if err == nil { + w.Write(b) + return true + } case wgkeyKeyType: if v.CanAddr() { x := v.Addr().Interface().(*wgkey.Key)