internal/deephash: simplify API

Reduce to just a single external endpoint.
Convert from a variadic number of interfaces to a slice there.

name    old time/op    new time/op    delta
Hash-8    14.4µs ± 0%    14.0µs ± 1%   -3.08%  (p=0.000 n=9+9)

name    old alloc/op   new alloc/op   delta
Hash-8      873B ± 0%      793B ± 0%   -9.16%  (p=0.000 n=9+6)

name    old allocs/op  new allocs/op  delta
Hash-8      18.0 ± 0%      14.0 ± 0%  -22.22%  (p=0.000 n=10+10)

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
pull/1980/head
Josh Bleecher Snyder 3 years ago committed by Josh Bleecher Snyder
parent b371588ce6
commit 988dfcabef

@ -19,18 +19,18 @@ import (
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
) )
func Hash(v ...interface{}) string { func calcHash(v interface{}) string {
h := sha256.New() h := sha256.New()
// 64 matches the chunk size in crypto/sha256/sha256.go // 64 matches the chunk size in crypto/sha256/sha256.go
b := bufio.NewWriterSize(h, 64) b := bufio.NewWriterSize(h, 64)
Print(b, v) printTo(b, v)
b.Flush() b.Flush()
return fmt.Sprintf("%x", h.Sum(nil)) return fmt.Sprintf("%x", h.Sum(nil))
} }
// UpdateHash sets last to the hash of v and reports whether its value changed. // UpdateHash sets last to the hash of v and reports whether its value changed.
func UpdateHash(last *string, v ...interface{}) (changed bool) { func UpdateHash(last *string, v ...interface{}) (changed bool) {
sig := Hash(v) sig := calcHash(v)
if *last != sig { if *last != sig {
*last = sig *last = sig
return true return true
@ -38,7 +38,7 @@ func UpdateHash(last *string, v ...interface{}) (changed bool) {
return false return false
} }
func Print(w *bufio.Writer, v ...interface{}) { func printTo(w *bufio.Writer, v interface{}) {
print(w, reflect.ValueOf(v), make(map[uintptr]bool)) print(w, reflect.ValueOf(v), make(map[uintptr]bool))
} }

@ -18,15 +18,15 @@ import (
"tailscale.com/wgengine/wgcfg" "tailscale.com/wgengine/wgcfg"
) )
func TestDeepPrint(t *testing.T) { func TestDeepHash(t *testing.T) {
// v contains the types of values we care about for our current callers. // v contains the types of values we care about for our current callers.
// Mostly we're just testing that we don't panic on handled types. // Mostly we're just testing that we don't panic on handled types.
v := getVal() v := getVal()
hash1 := Hash(v) hash1 := calcHash(v)
t.Logf("hash: %v", hash1) t.Logf("hash: %v", hash1)
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
hash2 := Hash(getVal()) hash2 := calcHash(getVal())
if hash1 != hash2 { if hash1 != hash2 {
t.Error("second hash didn't match") t.Error("second hash didn't match")
} }
@ -80,7 +80,7 @@ func BenchmarkHash(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
v := getVal() v := getVal()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Hash(v) calcHash(v)
} }
} }

Loading…
Cancel
Save