Skip to content

Commit

Permalink
Hash cashing.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Jul 19, 2017
1 parent f72aa22 commit 6f331f8
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 38 deletions.
3 changes: 1 addition & 2 deletions expreduce/builtin_comparison.go
Expand Up @@ -450,8 +450,7 @@ func getComparisonDefinitions() (defs []Definition) {
}
}
i -= 1
this.Parts = append([]Ex{this.Parts[0]}, this.Parts[i:]...)
return this
return NewExpression(append([]Ex{this.Parts[0]}, this.Parts[i:]...))
},
SimpleExamples: []TestInstruction{
&SameTest{"3", "Max[1,2,3]"},
Expand Down
1 change: 1 addition & 0 deletions expreduce/builtin_sort.go
Expand Up @@ -17,6 +17,7 @@ func GetSortDefinitions() (defs []Definition) {
exp, ok := this.Parts[1].(*Expression)
if ok {
sortedExp := exp.DeepCopy().(*Expression)
sortedExp.evaledHash = 0
sortedExp.cachedHash = 0
sort.Sort(sortedExp)
return sortedExp
Expand Down
5 changes: 1 addition & 4 deletions expreduce/builtin_system.go
Expand Up @@ -8,15 +8,12 @@ import "runtime/pprof"
import "log"
import "io/ioutil"
import "github.com/op/go-logging"
import "hash/fnv"
import "flag"

var mymemprofile = flag.String("mymemprofile", "", "write memory profile to this file")

func hashEx(e Ex) uint64 {
h := fnv.New64a()
e.Hash(&h)
return h.Sum64()
return e.Hash()
}

func exprToN(es *EvalState, e Ex) Ex {
Expand Down
4 changes: 1 addition & 3 deletions expreduce/cas.go
Expand Up @@ -4,8 +4,6 @@

package expreduce

import "hash"

type ToStringFnType (func(*Expression, string) (bool, string))

// A nasty global to keep track of ToString functions. TODO: Fix this.
Expand All @@ -19,5 +17,5 @@ type Ex interface {
IsEqual(b Ex, cl *CASLogger) string
DeepCopy() Ex
NeedsEval() bool
Hash(h *hash.Hash64)
Hash() uint64
}
32 changes: 24 additions & 8 deletions expreduce/ex_expression.go
Expand Up @@ -4,9 +4,10 @@ import "bytes"
import "math/big"
import "sort"
import "fmt"
import "encoding/binary"
import "time"
import "flag"
import "hash"
import "hash/fnv"

var printevals = flag.Bool("printevals", false, "")
var checkhashes = flag.Bool("checkhashes", false, "")
Expand All @@ -15,6 +16,7 @@ type Expression struct {
Parts []Ex
needsEval bool
correctlyInstantiated bool
evaledHash uint64
cachedHash uint64
}

Expand Down Expand Up @@ -103,7 +105,7 @@ func (this *Expression) Eval(es *EvalState) Ex {
lastExHash := uint64(0)
var lastEx Ex = this
currExHash := hashEx(this)
if currExHash == this.cachedHash {
if currExHash == this.evaledHash {
return this
}
var currEx Ex = this
Expand All @@ -112,7 +114,7 @@ func (this *Expression) Eval(es *EvalState) Ex {
lastExHash = currExHash
curr, isExpr := currEx.(*Expression)
if *checkhashes {
if isExpr && curr.cachedHash != 0 && currExHash != curr.cachedHash {
if isExpr && curr.evaledHash != 0 && currExHash != curr.evaledHash {
fmt.Printf("invalid cache: %v. Used to be %v\n", curr, lastEx)
}
lastEx = currEx
Expand All @@ -124,7 +126,7 @@ func (this *Expression) Eval(es *EvalState) Ex {
return retVal
}
}
if isExpr && currExHash == curr.cachedHash {
if isExpr && currExHash == curr.evaledHash {
return curr
}

Expand Down Expand Up @@ -184,7 +186,11 @@ func (this *Expression) Eval(es *EvalState) Ex {
if es.trace != nil && !es.IsFrozen() {
es.trace = NewExpression([]Ex{&Symbol{"List"}})
}
oldHash := curr.Parts[i].Hash()
curr.Parts[i] = curr.Parts[i].Eval(es)
if oldHash != curr.Parts[i].Hash() {
curr.cachedHash = 0
}
if es.trace != nil && !es.IsFrozen() {
if len(es.trace.Parts) > 2 {
// The DeepCopy here doesn't seem to affect anything, but
Expand Down Expand Up @@ -279,7 +285,7 @@ func (this *Expression) Eval(es *EvalState) Ex {
curr, isExpr := currEx.(*Expression)
if isExpr {
curr.needsEval = false
curr.cachedHash = currExHash
curr.evaledHash = currExHash
}
return currEx
}
Expand Down Expand Up @@ -421,6 +427,7 @@ func (this *Expression) DeepCopy() Ex {
}
thiscopy.needsEval = this.needsEval
thiscopy.correctlyInstantiated = this.correctlyInstantiated
thiscopy.evaledHash = this.evaledHash
thiscopy.cachedHash = this.cachedHash
return thiscopy
}
Expand All @@ -430,6 +437,7 @@ func (this *Expression) ShallowCopy() *Expression {
thiscopy.Parts = append([]Ex{}, this.Parts...)
thiscopy.needsEval = this.needsEval
thiscopy.correctlyInstantiated = this.correctlyInstantiated
thiscopy.evaledHash = this.evaledHash
thiscopy.cachedHash = this.cachedHash
return thiscopy
}
Expand All @@ -455,11 +463,19 @@ func (this *Expression) NeedsEval() bool {
return this.needsEval
}

func (this *Expression) Hash(h *hash.Hash64) {
(*h).Write([]byte{72, 5, 244, 86, 5, 210, 69, 30})
func (this *Expression) Hash() uint64 {
if this.cachedHash > 0 {
return this.cachedHash
}
h := fnv.New64a()
h.Write([]byte{72, 5, 244, 86, 5, 210, 69, 30})
for _, part := range this.Parts {
part.Hash(h)
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, part.Hash())
h.Write(b)
}
this.cachedHash = h.Sum64()
return h.Sum64()
}

func NewExpression(parts []Ex) *Expression {
Expand Down
10 changes: 6 additions & 4 deletions expreduce/ex_integer.go
Expand Up @@ -2,7 +2,7 @@ package expreduce

import "fmt"
import "math/big"
import "hash"
import "hash/fnv"

// Integer numbers represented by big.Int
type Integer struct {
Expand Down Expand Up @@ -54,10 +54,12 @@ func NewInt(i int64) *Integer {
return &Integer{big.NewInt(i)}
}

func (this *Integer) Hash(h *hash.Hash64) {
(*h).Write([]byte{242, 99, 84, 113, 102, 46, 118, 94})
func (this *Integer) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{242, 99, 84, 113, 102, 46, 118, 94})
bytes, _ := this.Val.MarshalText()
(*h).Write(bytes)
h.Write(bytes)
return h.Sum64()
}

func (this *Integer) AsBigFloat() *big.Float {
Expand Down
12 changes: 7 additions & 5 deletions expreduce/ex_rational.go
Expand Up @@ -2,7 +2,7 @@ package expreduce

import "fmt"
import "math/big"
import "hash"
import "hash/fnv"

type Rational struct {
Num *big.Int
Expand Down Expand Up @@ -96,12 +96,14 @@ func NewRational(n *big.Int, d *big.Int) *Rational {
return &Rational{n, d, true}
}

func (this *Rational) Hash(h *hash.Hash64) {
(*h).Write([]byte{90, 82, 214, 51, 52, 7, 7, 33})
func (this *Rational) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{90, 82, 214, 51, 52, 7, 7, 33})
nBytes, _ := this.Num.MarshalText()
(*h).Write(nBytes)
h.Write(nBytes)
dBytes, _ := this.Den.MarshalText()
(*h).Write(dBytes)
h.Write(dBytes)
return h.Sum64()
}

func (this *Rational) AsBigFloat() *big.Float {
Expand Down
10 changes: 6 additions & 4 deletions expreduce/ex_real.go
Expand Up @@ -3,7 +3,7 @@ package expreduce
import "fmt"
import "math/big"
import "bytes"
import "hash"
import "hash/fnv"

// Floating point numbers represented by big.Float
type Flt struct {
Expand Down Expand Up @@ -68,10 +68,12 @@ func (this *Flt) NeedsEval() bool {
return false
}

func (this *Flt) Hash(h *hash.Hash64) {
(*h).Write([]byte{195, 244, 76, 249, 227, 115, 88, 251})
func (this *Flt) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{195, 244, 76, 249, 227, 115, 88, 251})
bytes, _ := this.Val.MarshalText()
(*h).Write(bytes)
h.Write(bytes)
return h.Sum64()
}

func (this *Flt) AddI(i *Integer) {
Expand Down
10 changes: 6 additions & 4 deletions expreduce/ex_string.go
@@ -1,7 +1,7 @@
package expreduce

import "fmt"
import "hash"
import "hash/fnv"

type String struct {
Val string
Expand Down Expand Up @@ -42,7 +42,9 @@ func (this *String) NeedsEval() bool {
return false
}

func (this *String) Hash(h *hash.Hash64) {
(*h).Write([]byte{102, 206, 57, 172, 207, 100, 198, 133})
(*h).Write([]byte(this.Val))
func (this *String) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{102, 206, 57, 172, 207, 100, 198, 133})
h.Write([]byte(this.Val))
return h.Sum64()
}
10 changes: 6 additions & 4 deletions expreduce/ex_symbol.go
Expand Up @@ -2,7 +2,7 @@ package expreduce

import "fmt"
import "sort"
import "hash"
import "hash/fnv"

// Symbols are defined by a string-based name
type Symbol struct {
Expand Down Expand Up @@ -229,9 +229,11 @@ func (this *Symbol) NeedsEval() bool {
return false
}

func (this *Symbol) Hash(h *hash.Hash64) {
(*h).Write([]byte{107, 10, 247, 23, 33, 221, 163, 156})
(*h).Write([]byte(this.Name))
func (this *Symbol) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{107, 10, 247, 23, 33, 221, 163, 156})
h.Write([]byte(this.Name))
return h.Sum64()
}

func ContainsSymbol(e Ex, name string) bool {
Expand Down
1 change: 1 addition & 0 deletions expreduce/replace.go
Expand Up @@ -52,6 +52,7 @@ func ReplacePDInternal(e Ex, pm *PDManager) Ex {
}
asExpr, isExpr := e.(*Expression)
if isExpr {
asExpr.evaledHash = 0
asExpr.cachedHash = 0
for i := range asExpr.Parts {
asExpr.Parts[i] = ReplacePDInternal(asExpr.Parts[i], pm)
Expand Down

0 comments on commit 6f331f8

Please sign in to comment.