mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-01 14:05:39 +00:00
util/deephash: avoid using sync.Pool for reflect.MapIter (#5333)
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 <joetsai@digital-static.net>
This commit is contained in:
parent
5d731ca13f
commit
77a92f326d
@ -919,7 +919,6 @@ func (h *hasher) hashValueWithType(v addressableValue, ti *typeInfo, forceCycleC
|
|||||||
type mapHasher struct {
|
type mapHasher struct {
|
||||||
h hasher
|
h hasher
|
||||||
valKey, valElem valueCache // re-usable values for map iteration
|
valKey, valElem valueCache // re-usable values for map iteration
|
||||||
iter reflect.MapIter // re-usable map iterator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapHasherPool = &sync.Pool{
|
var mapHasherPool = &sync.Pool{
|
||||||
@ -948,10 +947,6 @@ func (h *hasher) hashMap(v addressableValue, ti *typeInfo, checkCycles bool) {
|
|||||||
mh := mapHasherPool.Get().(*mapHasher)
|
mh := mapHasherPool.Get().(*mapHasher)
|
||||||
defer mapHasherPool.Put(mh)
|
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
|
var sum Sum
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
sum.sum[0] = 1 // something non-zero
|
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())
|
k := mh.valKey.get(v.Type().Key())
|
||||||
e := mh.valElem.get(v.Type().Elem())
|
e := mh.valElem.get(v.Type().Elem())
|
||||||
mh.h.visitStack = h.visitStack // always use the parent's visit stack to avoid cycles
|
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)
|
k.SetIterKey(iter)
|
||||||
e.SetIterValue(iter)
|
e.SetIterValue(iter)
|
||||||
mh.h.reset()
|
mh.h.reset()
|
||||||
|
Loading…
Reference in New Issue
Block a user