Add treapNode pool. Reduce cloneTreapNode() allocations. #47
4 changed files with 75 additions and 9 deletions
|
@ -516,6 +516,9 @@ func (c *dbCache) flush() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedKeys.Recycle()
|
||||||
|
cachedRemove.Recycle()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,9 +577,16 @@ func (c *dbCache) commitTx(tx *transaction) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pk := tx.pendingKeys
|
||||||
|
pr := tx.pendingRemove
|
||||||
|
|
||||||
// Clear the transaction entries since they have been committed.
|
// Clear the transaction entries since they have been committed.
|
||||||
tx.pendingKeys = nil
|
tx.pendingKeys = nil
|
||||||
tx.pendingRemove = nil
|
tx.pendingRemove = nil
|
||||||
|
|
||||||
|
pk.Recycle()
|
||||||
|
pr.Recycle()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,13 @@ type treapNode struct {
|
||||||
right *treapNode
|
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
|
// nodeSize returns the number of bytes the specified node occupies including
|
||||||
// the struct fields and the contents of the key and value.
|
// the struct fields and the contents of the key and value.
|
||||||
func nodeSize(node *treapNode) uint64 {
|
func nodeSize(node *treapNode) uint64 {
|
||||||
|
|
|
@ -7,17 +7,20 @@ package treap
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var nodePool = &sync.Pool{New: func() interface{} { return newTreapNode(nil, nil, 0) }}
|
||||||
|
|
||||||
// cloneTreapNode returns a shallow copy of the passed node.
|
// cloneTreapNode returns a shallow copy of the passed node.
|
||||||
func cloneTreapNode(node *treapNode) *treapNode {
|
func cloneTreapNode(node *treapNode) *treapNode {
|
||||||
return &treapNode{
|
clone := nodePool.Get().(*treapNode)
|
||||||
key: node.key,
|
clone.key = node.key
|
||||||
value: node.value,
|
clone.value = node.value
|
||||||
priority: node.priority,
|
clone.priority = node.priority
|
||||||
left: node.left,
|
clone.left = node.left
|
||||||
right: node.right,
|
clone.right = node.right
|
||||||
}
|
return clone
|
||||||
}
|
}
|
||||||
|
|
||||||
// Immutable represents a treap data structure which is used to hold ordered
|
// 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.
|
// 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)
|
parent := parents.At(0)
|
||||||
if compareResult < 0 {
|
if compareResult < 0 {
|
||||||
parent.left = node
|
parent.left = node
|
||||||
|
@ -358,3 +364,23 @@ func (t *Immutable) ForEach(fn func(k, v []byte) bool) {
|
||||||
func NewImmutable() *Immutable {
|
func NewImmutable() *Immutable {
|
||||||
return &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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -145,7 +145,10 @@ func (t *Mutable) Put(key, value []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link the new node into the binary tree in the correct position.
|
// 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.count++
|
||||||
t.totalSize += nodeSize(node)
|
t.totalSize += nodeSize(node)
|
||||||
parent := parents.At(0)
|
parent := parents.At(0)
|
||||||
|
@ -276,3 +279,23 @@ func (t *Mutable) Reset() {
|
||||||
func NewMutable() *Mutable {
|
func NewMutable() *Mutable {
|
||||||
return &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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue