Skip to content

Commit 2d4b162

Browse files
Improve rootkey cache in pruning: Reduce 4 rootkey fetches to 1 (backport #1029) (#1030)
Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
1 parent 6bb9c64 commit 2d4b162

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

nodedb.go

+32-10
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,22 @@ func (ndb *nodeDB) saveNodeFromPruning(node *Node) error {
416416
return ndb.batch.Set(ndb.nodeKey(node.GetKey()), buf.Bytes())
417417
}
418418

419+
// rootkey cache of two elements, attempting to mimic a direct-mapped cache.
419420
type rootkeyCache struct {
420-
version int64
421-
rootKey []byte
421+
// initial value is set to {-1, -1}, which is an invalid version for a getrootkey call.
422+
versions [2]int64
423+
rootKeys [2][]byte
424+
next int
422425
}
423426

424427
func (rkc *rootkeyCache) getRootKey(ndb *nodeDB, version int64) ([]byte, error) {
425-
if rkc.version == version {
426-
return rkc.rootKey, nil
428+
// Check both cache entries
429+
for i := 0; i < 2; i++ {
430+
if rkc.versions[i] == version {
431+
return rkc.rootKeys[i], nil
432+
}
427433
}
434+
428435
rootKey, err := ndb.GetRoot(version)
429436
if err != nil {
430437
return nil, err
@@ -434,8 +441,18 @@ func (rkc *rootkeyCache) getRootKey(ndb *nodeDB, version int64) ([]byte, error)
434441
}
435442

436443
func (rkc *rootkeyCache) setRootKey(version int64, rootKey []byte) {
437-
rkc.version = version
438-
rkc.rootKey = rootKey
444+
// Store in next available slot, cycling between 0 and 1
445+
rkc.versions[rkc.next] = version
446+
rkc.rootKeys[rkc.next] = rootKey
447+
rkc.next = (rkc.next + 1) % 2
448+
}
449+
450+
func newRootkeyCache() *rootkeyCache {
451+
return &rootkeyCache{
452+
versions: [2]int64{-1, -1},
453+
rootKeys: [2][]byte{},
454+
next: 0,
455+
}
439456
}
440457

441458
// deleteVersion deletes a tree version from disk.
@@ -446,7 +463,7 @@ func (ndb *nodeDB) deleteVersion(version int64, cache *rootkeyCache) error {
446463
return err
447464
}
448465

449-
if err := ndb.traverseOrphans(version, version+1, func(orphan *Node) error {
466+
if err := ndb.traverseOrphansWithRootkeyCache(cache, version, version+1, func(orphan *Node) error {
450467
if orphan.nodeKey.nonce == 0 && !orphan.isLegacy {
451468
// if the orphan is a reformatted root, it can be a legacy root
452469
// so it should be removed from the pruning process.
@@ -708,7 +725,7 @@ func (ndb *nodeDB) deleteVersionsTo(toVersion int64) error {
708725
ndb.resetLegacyLatestVersion(-1)
709726
}
710727

711-
rootkeyCache := &rootkeyCache{}
728+
rootkeyCache := newRootkeyCache()
712729
for version := first; version <= toVersion; version++ {
713730
if err := ndb.deleteVersion(version, rootkeyCache); err != nil {
714731
return err
@@ -1095,7 +1112,12 @@ func isReferenceRoot(bz []byte) (bool, int) {
10951112
// traverseOrphans traverses orphans which removed by the updates of the curVersion in the prevVersion.
10961113
// NOTE: it is used for both legacy and new nodes.
10971114
func (ndb *nodeDB) traverseOrphans(prevVersion, curVersion int64, fn func(*Node) error) error {
1098-
curKey, err := ndb.GetRoot(curVersion)
1115+
cache := newRootkeyCache()
1116+
return ndb.traverseOrphansWithRootkeyCache(cache, prevVersion, curVersion, fn)
1117+
}
1118+
1119+
func (ndb *nodeDB) traverseOrphansWithRootkeyCache(cache *rootkeyCache, prevVersion, curVersion int64, fn func(*Node) error) error {
1120+
curKey, err := cache.getRootKey(ndb, curVersion)
10991121
if err != nil {
11001122
return err
11011123
}
@@ -1105,7 +1127,7 @@ func (ndb *nodeDB) traverseOrphans(prevVersion, curVersion int64, fn func(*Node)
11051127
return err
11061128
}
11071129

1108-
prevKey, err := ndb.GetRoot(prevVersion)
1130+
prevKey, err := cache.getRootKey(ndb, prevVersion)
11091131
if err != nil {
11101132
return err
11111133
}

0 commit comments

Comments
 (0)