From 77a92f326d3cd82334c5fb1aabf777303254c0b4 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 11 Aug 2022 00:33:40 -0700 Subject: [PATCH] util/deephash: avoid using sync.Pool for reflect.MapIter (#5333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Go 1.19, the reflect.Value.MapRange method uses "function outlining" so that the allocation of reflect.MapIter is inlinable by the caller. If the iterator doesn't escape the caller, it can be stack allocated. See https://go.dev/cl/400675 Performance: name old time/op new time/op delta HashMapAcyclic-24 31.9µs ± 2% 32.1µs ± 1% ~ (p=0.075 n=10+10) name old alloc/op new alloc/op delta HashMapAcyclic-24 0.00B 0.00B ~ (all equal) Signed-off-by: Joe Tsai --- util/deephash/deephash.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/util/deephash/deephash.go b/util/deephash/deephash.go index 5add5a82e..a1b70906f 100644 --- a/util/deephash/deephash.go +++ b/util/deephash/deephash.go @@ -918,8 +918,7 @@ func (h *hasher) hashValueWithType(v addressableValue, ti *typeInfo, forceCycleC type mapHasher struct { h hasher - valKey, valElem valueCache // re-usable values for map iteration - iter reflect.MapIter // re-usable map iterator + valKey, valElem valueCache // re-usable values for map iteration } var mapHasherPool = &sync.Pool{ @@ -948,10 +947,6 @@ func (h *hasher) hashMap(v addressableValue, ti *typeInfo, checkCycles bool) { mh := mapHasherPool.Get().(*mapHasher) defer mapHasherPool.Put(mh) - iter := &mh.iter - iter.Reset(v.Value) - defer iter.Reset(reflect.Value{}) // avoid pinning v from mh.iter when we return - var sum Sum if v.IsNil() { sum.sum[0] = 1 // something non-zero @@ -960,7 +955,7 @@ func (h *hasher) hashMap(v addressableValue, ti *typeInfo, checkCycles bool) { k := mh.valKey.get(v.Type().Key()) e := mh.valElem.get(v.Type().Elem()) mh.h.visitStack = h.visitStack // always use the parent's visit stack to avoid cycles - for iter.Next() { + for iter := v.MapRange(); iter.Next(); { k.SetIterKey(iter) e.SetIterValue(iter) mh.h.reset()