mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
util/deephash: move pointer and interface logic to separate function (#5465)
This helps pprof better identify which Go kinds take the most time since the kind is always in the function name. Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
parent
d2e2d8438b
commit
c5b1565337
@ -255,42 +255,9 @@ func genTypeHasher(ti *typeInfo) typeHasherFunc {
|
|||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return makeMapHasher(t)
|
return makeMapHasher(t)
|
||||||
case reflect.Pointer:
|
case reflect.Pointer:
|
||||||
et := t.Elem()
|
return makePointerHasher(t)
|
||||||
eti := getTypeInfo(et)
|
|
||||||
return func(h *hasher, p pointer) {
|
|
||||||
pe := p.pointerElem()
|
|
||||||
if pe.isNil() {
|
|
||||||
h.HashUint8(0) // indicates nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ti.isRecursive {
|
|
||||||
if idx, ok := h.visitStack.seen(pe.p); ok {
|
|
||||||
h.HashUint8(2) // indicates cycle
|
|
||||||
h.HashUint64(uint64(idx))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.visitStack.push(pe.p)
|
|
||||||
defer h.visitStack.pop(pe.p)
|
|
||||||
}
|
|
||||||
h.HashUint8(1) // indicates visiting a pointer
|
|
||||||
eti.hasher()(h, pe)
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
return func(h *hasher, p pointer) {
|
return makeInterfaceHasher(t)
|
||||||
v := p.asValue(t).Elem() // reflect.Interface kind
|
|
||||||
if v.IsNil() {
|
|
||||||
h.HashUint8(0) // indicates nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.HashUint8(1) // visiting interface
|
|
||||||
v = v.Elem()
|
|
||||||
t := v.Type()
|
|
||||||
h.hashType(t)
|
|
||||||
va := reflect.New(t).Elem()
|
|
||||||
va.Set(v)
|
|
||||||
ti := getTypeInfo(t)
|
|
||||||
ti.hasher()(h, pointerOf(va.Addr()))
|
|
||||||
}
|
|
||||||
default: // Func, Chan, UnsafePointer
|
default: // Func, Chan, UnsafePointer
|
||||||
return func(*hasher, pointer) {}
|
return func(*hasher, pointer) {}
|
||||||
}
|
}
|
||||||
@ -490,6 +457,53 @@ func makeMapHasher(t reflect.Type) typeHasherFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makePointerHasher(t reflect.Type) typeHasherFunc {
|
||||||
|
var once sync.Once
|
||||||
|
var hashElem typeHasherFunc
|
||||||
|
var isRecursive bool
|
||||||
|
init := func() {
|
||||||
|
hashElem = getTypeInfo(t.Elem()).hasher()
|
||||||
|
isRecursive = typeIsRecursive(t)
|
||||||
|
}
|
||||||
|
return func(h *hasher, p pointer) {
|
||||||
|
pe := p.pointerElem()
|
||||||
|
if pe.isNil() {
|
||||||
|
h.HashUint8(0) // indicates nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
once.Do(init)
|
||||||
|
if isRecursive {
|
||||||
|
if idx, ok := h.visitStack.seen(pe.p); ok {
|
||||||
|
h.HashUint8(2) // indicates cycle
|
||||||
|
h.HashUint64(uint64(idx))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.visitStack.push(pe.p)
|
||||||
|
defer h.visitStack.pop(pe.p)
|
||||||
|
}
|
||||||
|
h.HashUint8(1) // indicates visiting a pointer element
|
||||||
|
hashElem(h, pe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeInterfaceHasher(t reflect.Type) typeHasherFunc {
|
||||||
|
return func(h *hasher, p pointer) {
|
||||||
|
v := p.asValue(t).Elem() // reflect.Interface kind
|
||||||
|
if v.IsNil() {
|
||||||
|
h.HashUint8(0) // indicates nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.HashUint8(1) // indicates visiting an interface value
|
||||||
|
v = v.Elem()
|
||||||
|
t := v.Type()
|
||||||
|
h.hashType(t)
|
||||||
|
va := reflect.New(t).Elem()
|
||||||
|
va.Set(v)
|
||||||
|
hashElem := getTypeInfo(t).hasher()
|
||||||
|
hashElem(h, pointerOf(va.Addr()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getTypeInfo(t reflect.Type) *typeInfo {
|
func getTypeInfo(t reflect.Type) *typeInfo {
|
||||||
if f, ok := typeInfoMap.Load(t); ok {
|
if f, ok := typeInfoMap.Load(t); ok {
|
||||||
return f.(*typeInfo)
|
return f.(*typeInfo)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user