From 645c6bc0c84a4ccfcc06cf7cb6bebef4e1e435ce Mon Sep 17 00:00:00 2001 From: Torin Sandall Date: Thu, 7 Jul 2016 10:20:57 -0700 Subject: [PATCH] Optimization: Improve string and var term hashing Use siphash for more efficient string hashing and avoid copy in string to byte conversion. --- ast/term.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/ast/term.go b/ast/term.go index fc938055ba..122a357c58 100644 --- a/ast/term.go +++ b/ast/term.go @@ -7,10 +7,14 @@ package ast import ( "encoding/json" "fmt" - "hash/fnv" + "math/rand" "regexp" "strconv" "strings" + "time" + "unsafe" + + "github.com/dchest/siphash" "github.com/pkg/errors" ) @@ -329,9 +333,8 @@ func (str String) String() string { // Hash returns the hash code for the Value. func (str String) Hash() int { - h := fnv.New64a() - h.Write([]byte(str)) - return int(h.Sum64()) + h := siphash.Hash(hashSeed0, hashSeed1, *(*[]byte)(unsafe.Pointer(&str))) + return int(h) } // Var represents a variable as defined by the language. @@ -355,9 +358,8 @@ func (variable Var) Equal(other Value) bool { // Hash returns the hash code for the Value. func (variable Var) Hash() int { - h := fnv.New64a() - h.Write([]byte(variable)) - return int(h.Sum64()) + h := siphash.Hash(hashSeed0, hashSeed1, *(*[]byte)(unsafe.Pointer(&variable))) + return int(h) } // IsGround always returns false. @@ -978,3 +980,16 @@ func unmarshalValue(d map[string]interface{}) (Value, error) { unmarshal_error: return nil, fmt.Errorf("ast: unable to unmarshal term") } + +var hashSeed0 uint64 +var hashSeed1 uint64 + +func initHashSeed() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + hashSeed0 = (uint64(r.Uint32()) << 32) | uint64(r.Uint32()) + hashSeed1 = (uint64(r.Uint32()) << 32) | uint64(r.Uint32()) +} + +func init() { + initHashSeed() +}