diff --git a/cache/cache.go b/cache/cache.go index 04375838e..43f5146e8 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -32,6 +32,9 @@ type Cache interface { // Len returns the cache length. Len() int + + // Capacity returns the maximum number of nodes the cache can hold. + Capacity() int } // lruCache is an LRU cache implementation. @@ -96,6 +99,10 @@ func (c *lruCache) Len() int { return c.ll.Len() } +func (c *lruCache) Capacity() int { + return c.maxElementCount +} + func (c *lruCache) Remove(key []byte) Node { if elem, exists := c.dict[string(key)]; exists { return c.removeWithKey(elem, string(key)) diff --git a/mutable_tree.go b/mutable_tree.go index 6308c35ab..0eeb0472a 100644 --- a/mutable_tree.go +++ b/mutable_tree.go @@ -745,7 +745,7 @@ func (tree *MutableTree) SaveVersion() ([]byte, int64, error) { // it will update the legacy node to the new format // which ensures the reference node is not a legacy node tree.root.isLegacy = false - if err := tree.ndb.SaveNode(tree.root); err != nil { + if err := tree.ndb.SaveNode(tree.root, true); err != nil { return nil, 0, fmt.Errorf("failed to save the reference legacy node: %w", err) } } @@ -1044,8 +1044,11 @@ func (tree *MutableTree) saveNewNodes(version int64) error { return err } - for _, node := range newNodes { - if err := tree.ndb.SaveNode(node); err != nil { + cacheCapacity := tree.ndb.nodeCache.Capacity() + for i, node := range newNodes { + // only add up to cacheCapacity nodes to the cache + addToLruCache := i < cacheCapacity + if err := tree.ndb.SaveNode(node, addToLruCache); err != nil { return err } node.leftNode, node.rightNode = nil, nil diff --git a/nodedb.go b/nodedb.go index dc0bc9f4b..6d097f37a 100644 --- a/nodedb.go +++ b/nodedb.go @@ -204,7 +204,7 @@ func (ndb *nodeDB) GetFastNode(key []byte) (*fastnode.Node, error) { } // SaveNode saves a node to disk. -func (ndb *nodeDB) SaveNode(node *Node) error { +func (ndb *nodeDB) SaveNode(node *Node, useLruCache bool) error { ndb.mtx.Lock() defer ndb.mtx.Unlock() @@ -225,7 +225,9 @@ func (ndb *nodeDB) SaveNode(node *Node) error { } ndb.logger.Debug("BATCH SAVE", "node", node) - ndb.nodeCache.Add(node) + if useLruCache { + ndb.nodeCache.Add(node) + } return nil } @@ -386,7 +388,7 @@ func (ndb *nodeDB) deleteVersion(version int64) error { } // instead, the root should be reformatted to (version, 0) root.nodeKey.nonce = 0 - if err := ndb.SaveNode(root); err != nil { + if err := ndb.SaveNode(root, true); err != nil { return err } } diff --git a/tree_test.go b/tree_test.go index 9c564b29a..8a44eefa3 100644 --- a/tree_test.go +++ b/tree_test.go @@ -1775,7 +1775,7 @@ func TestNodeCacheStatisic(t *testing.T) { expectCacheMissCnt int }{ "with_cache": { - cacheSize: numKeyVals, + cacheSize: 2 * numKeyVals, // has to cover all inner nodes expectFastCacheHitCnt: numKeyVals, expectFastCacheMissCnt: 0, expectCacheHitCnt: 1,