recycle treap nodes

This commit is contained in:
Brannon King 2021-07-22 11:24:05 -04:00 committed by Roy Lee
parent 357d875251
commit 3b25c33e23
4 changed files with 78 additions and 14 deletions

View file

@ -502,6 +502,8 @@ func (c *dbCache) flush() error {
c.cacheLock.RLock()
cachedKeys := c.cachedKeys
cachedRemove := c.cachedRemove
c.cachedKeys = treap.NewImmutable()
c.cachedRemove = treap.NewImmutable()
c.cacheLock.RUnlock()
// Nothing to do if there is no data to flush.
@ -514,11 +516,8 @@ func (c *dbCache) flush() error {
return err
}
// Clear the cache since it has been flushed.
c.cacheLock.Lock()
c.cachedKeys = treap.NewImmutable()
c.cachedRemove = treap.NewImmutable()
c.cacheLock.Unlock()
cachedKeys.Recycle()
cachedRemove.Recycle()
return nil
}
@ -578,9 +577,16 @@ func (c *dbCache) commitTx(tx *transaction) error {
return err
}
pk := tx.pendingKeys
pr := tx.pendingRemove
// Clear the transaction entries since they have been committed.
tx.pendingKeys = nil
tx.pendingRemove = nil
pk.Recycle()
pr.Recycle()
return nil
}

View file

@ -42,6 +42,13 @@ type treapNode struct {
right *treapNode
}
func (n *treapNode) Reset() {
n.key = nil
n.value = nil
n.left = nil
n.right = nil
}
// nodeSize returns the number of bytes the specified node occupies including
// the struct fields and the contents of the key and value.
func nodeSize(node *treapNode) uint64 {

View file

@ -7,17 +7,20 @@ package treap
import (
"bytes"
"math/rand"
"sync"
)
var nodePool = &sync.Pool{New: func() interface{} { return newTreapNode(nil, nil, 0) }}
// cloneTreapNode returns a shallow copy of the passed node.
func cloneTreapNode(node *treapNode) *treapNode {
return &treapNode{
key: node.key,
value: node.value,
priority: node.priority,
left: node.left,
right: node.right,
}
clone := nodePool.Get().(*treapNode)
clone.key = node.key
clone.value = node.value
clone.priority = node.priority
clone.left = node.left
clone.right = node.right
return clone
}
// Immutable represents a treap data structure which is used to hold ordered
@ -165,7 +168,10 @@ func (t *Immutable) Put(key, value []byte) *Immutable {
}
// Link the new node into the binary tree in the correct position.
node := newTreapNode(key, value, rand.Int())
node := nodePool.Get().(*treapNode)
node.key = key
node.value = value
node.priority = rand.Int()
parent := parents.At(0)
if compareResult < 0 {
parent.left = node
@ -358,3 +364,24 @@ func (t *Immutable) ForEach(fn func(k, v []byte) bool) {
func NewImmutable() *Immutable {
return &Immutable{}
}
func (t *Immutable) Recycle() {
var parents parentStack
for node := t.root; node != nil; node = node.left {
parents.Push(node)
}
for parents.Len() > 0 {
node := parents.Pop()
// Extend the nodes to traverse by all children to the left of
// the current node's right child.
for n := node.right; n != nil; n = n.left {
parents.Push(n)
}
node.Reset()
nodePool.Put(node)
}
}

View file

@ -145,7 +145,10 @@ func (t *Mutable) Put(key, value []byte) {
}
// Link the new node into the binary tree in the correct position.
node := newTreapNode(key, value, rand.Int())
node := nodePool.Get().(*treapNode)
node.key = key
node.value = value
node.priority = rand.Int()
t.count++
t.totalSize += nodeSize(node)
parent := parents.At(0)
@ -276,3 +279,24 @@ func (t *Mutable) Reset() {
func NewMutable() *Mutable {
return &Mutable{}
}
func (t *Mutable) Recycle() {
var parents parentStack
for node := t.root; node != nil; node = node.left {
parents.Push(node)
}
for parents.Len() > 0 {
node := parents.Pop()
// Extend the nodes to traverse by all children to the left of
// the current node's right child.
for n := node.right; n != nil; n = n.left {
parents.Push(n)
}
node.Reset()
nodePool.Put(node)
}
}