mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
util/deephash: move array and slice logic to separate function (#5463)
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
31bf3874d6
commit
296b008b9f
@ -312,25 +312,10 @@ func genTypeHasher(ti *typeInfo) typeHasherFunc {
|
|||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return (*hasher).hashString
|
return (*hasher).hashString
|
||||||
case reflect.Slice:
|
|
||||||
et := t.Elem()
|
|
||||||
if typeIsMemHashable(et) {
|
|
||||||
return func(h *hasher, p pointer) {
|
|
||||||
pa := p.sliceArray()
|
|
||||||
vLen := p.sliceLen()
|
|
||||||
h.HashUint64(uint64(vLen))
|
|
||||||
if vLen == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
h.HashBytes(pa.asMemory(et.Size() * uintptr(vLen)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eti := getTypeInfo(et)
|
|
||||||
return genHashSliceElements(eti)
|
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
et := t.Elem()
|
return makeArrayHasher(t)
|
||||||
eti := getTypeInfo(et)
|
case reflect.Slice:
|
||||||
return genHashArray(t, eti)
|
return makeSliceHasher(t)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return genHashStructFields(t)
|
return genHashStructFields(t)
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
@ -442,37 +427,50 @@ func makeMemHasher(n uintptr) typeHasherFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genHashArrayElements(n int, eti *typeInfo) typeHasherFunc {
|
func makeArrayHasher(t reflect.Type) typeHasherFunc {
|
||||||
nb := eti.rtype.Size() // byte size of each array element
|
var once sync.Once
|
||||||
|
var hashElem typeHasherFunc
|
||||||
|
init := func() {
|
||||||
|
hashElem = getTypeInfo(t.Elem()).hasher()
|
||||||
|
}
|
||||||
|
|
||||||
|
n := t.Len() // number of array elements
|
||||||
|
nb := t.Elem().Size() // byte size of each array element
|
||||||
return func(h *hasher, p pointer) {
|
return func(h *hasher, p pointer) {
|
||||||
|
once.Do(init)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
pe := p.arrayIndex(i, nb)
|
hashElem(h, p.arrayIndex(i, nb))
|
||||||
eti.hasher()(h, pe)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genHashArray(t reflect.Type, eti *typeInfo) typeHasherFunc {
|
func makeSliceHasher(t reflect.Type) typeHasherFunc {
|
||||||
n := t.Len()
|
nb := t.Elem().Size() // byte size of each slice element
|
||||||
return genHashArrayElements(n, eti)
|
if typeIsMemHashable(t.Elem()) {
|
||||||
}
|
return func(h *hasher, p pointer) {
|
||||||
|
pa := p.sliceArray()
|
||||||
|
n := p.sliceLen()
|
||||||
|
b := pa.asMemory(uintptr(n) * nb)
|
||||||
|
h.HashUint64(uint64(n))
|
||||||
|
h.HashBytes(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func genHashSliceElements(eti *typeInfo) typeHasherFunc {
|
var once sync.Once
|
||||||
return sliceElementHasher{eti}.hash
|
var hashElem typeHasherFunc
|
||||||
}
|
init := func() {
|
||||||
|
hashElem = getTypeInfo(t.Elem()).hasher()
|
||||||
|
}
|
||||||
|
|
||||||
type sliceElementHasher struct {
|
return func(h *hasher, p pointer) {
|
||||||
eti *typeInfo
|
pa := p.sliceArray()
|
||||||
}
|
once.Do(init)
|
||||||
|
n := p.sliceLen()
|
||||||
func (seh sliceElementHasher) hash(h *hasher, p pointer) {
|
h.HashUint64(uint64(n))
|
||||||
pa := p.sliceArray()
|
for i := 0; i < n; i++ {
|
||||||
vLen := p.sliceLen()
|
pe := pa.arrayIndex(i, nb)
|
||||||
h.HashUint64(uint64(vLen))
|
hashElem(h, pe)
|
||||||
nb := seh.eti.rtype.Size()
|
}
|
||||||
for i := 0; i < vLen; i++ {
|
|
||||||
pe := pa.arrayIndex(i, nb)
|
|
||||||
seh.eti.hasher()(h, pe)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user