diff --git a/benchmark_test.go b/benchmark_test.go index d91d05d..f102b94 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -// go test -benchtime=10000x -bench=BenchmarkQuantum -run=^$ -cpuprofile profile.out +// go test -benchtime=100x -bench=BenchmarkQuantum -run=^$ -cpuprofile profile.out // go tool pprof -http="localhost:8000" pprofbin ./profile.out type key struct { @@ -34,9 +34,13 @@ func BenchmarkMaps(b *testing.B) { for range b.N { b.StartTimer() - for i := range 10 { - for j := i * 10; j < i*10+100; j++ { - snapshot2[keys[j]] = j + for i := range 1000 { + for j := i * 10; j < i*10+10; j++ { + k := keys[j] + v2 := snapshot2[k] + v1 := snapshot1[k] + v := db[k] + snapshot2[k] = v + v1 + v2 + j } for k, v := range snapshot2 { snapshot1[k] = v @@ -70,10 +74,12 @@ func BenchmarkQuantum(b *testing.B) { for range b.N { b.StartTimer() snapshot1 := db.Next() - for i := range 10 { + for i := range 1000 { snapshot2 := snapshot1.Next() - for j := i * 10; j < i*10+100; j++ { - snapshot2.Set(keys[j], j) + for j := i * 10; j < i*10+10; j++ { + k := keys[j] + v, _ := snapshot2.Get(k) + snapshot2.Set(k, v+j) } snapshot1 = snapshot2 } diff --git a/quantum.go b/quantum.go index 1f3f91e..793ccb1 100644 --- a/quantum.go +++ b/quantum.go @@ -15,8 +15,6 @@ import ( func New[K comparable, V any]() Snapshot[K, V] { massNodes := mass.New[node[K, V]](1000) return Snapshot[K, V]{ - root: massNodes.New(), - rootSet: new(bool), massNodes: massNodes, defaultValue: *new(V), } @@ -26,7 +24,6 @@ func New[K comparable, V any]() Snapshot[K, V] { type Snapshot[K comparable, V any] struct { version uint64 root *node[K, V] - rootSet *bool massNodes *mass.Mass[node[K, V]] defaultValue V hasher hasher[K] @@ -36,18 +33,11 @@ type Snapshot[K comparable, V any] struct { // Next transitions to the next snapshot of the state. func (s Snapshot[K, V]) Next() Snapshot[K, V] { s.version++ - - r := *s.root - s.root = &r - - rs := *s.rootSet - s.rootSet = &rs - return s } // Get gets the value of the key. -func (s Snapshot[K, V]) Get(key K) (value V, exists bool) { +func (s *Snapshot[K, V]) Get(key K) (value V, exists bool) { h := s.hasher.Hash(key) n := s.root for { @@ -80,7 +70,7 @@ func (s Snapshot[K, V]) Get(key K) (value V, exists bool) { } // Set sets the value for the key. -func (s Snapshot[K, V]) Set(key K, value V) { +func (s *Snapshot[K, V]) Set(key K, value V) { const ( leftChild int = iota rightChild @@ -88,17 +78,6 @@ func (s Snapshot[K, V]) Set(key K, value V) { h := s.hasher.Hash(key) - if !*s.rootSet { - *s.root = node[K, V]{ - Key: key, - Value: value, - Version: s.version, - Hash: h, - } - *s.rootSet = true - return - } - var parentNode *node[K, V] var child int n := s.root @@ -110,11 +89,19 @@ func (s Snapshot[K, V]) Set(key K, value V) { n.Version = s.version n.Hash = h - if child == leftChild { + if s.root == nil { + s.root = n + return + } + switch { + case s.root == nil: + s.root = n + case child == leftChild: parentNode.Left = n - } else { + default: parentNode.Right = n } + return } if n.Version < s.version { @@ -126,19 +113,18 @@ func (s Snapshot[K, V]) Set(key K, value V) { n2.Left = n.Left n2.Right = n.Right n2.hasher = n.hasher + n = n2 switch { case parentNode == nil: - *s.root = *n2 - n = s.root + s.root = n case child == leftChild: - n = n2 parentNode.Left = n default: - n = n2 parentNode.Right = n } } + if n.Hash == h { if n.Key == key { n.Value = value