Skip to content
This repository was archived by the owner on Dec 28, 2022. It is now read-only.

Commit 6985b21

Browse files
committed
add small merkle tree cache
1 parent 528de13 commit 6985b21

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

lib/merkle-tree.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
const flat = require('flat-tree')
22
const crypto = require('hypercore-crypto')
33
const c = require('compact-encoding')
4+
const Xache = require('xache')
45
const b4a = require('b4a')
56
const caps = require('./caps')
67

78
const BLANK_HASH = b4a.alloc(32)
89
const OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98])
10+
const TREE_CACHE = 128 // speeds up linear scans by A LOT
911

1012
class NodeQueue {
1113
constructor (nodes, extra = null) {
@@ -140,6 +142,7 @@ class MerkleTreeBatch {
140142
: this.ancestors
141143

142144
this.tree.truncated = true
145+
this.tree.cache = new Xache({ maxSize: this.tree.cache.maxSize })
143146
truncateMap(this.tree.unflushed, this.ancestors)
144147
if (this.tree.flushing !== null) truncateMap(this.tree.flushing, this.ancestors)
145148
}
@@ -350,6 +353,7 @@ module.exports = class MerkleTree {
350353

351354
this.storage = storage
352355
this.unflushed = new Map()
356+
this.cache = new Xache({ maxSize: TREE_CACHE })
353357
this.flushing = null
354358
this.truncated = false
355359
this.truncateTo = 0
@@ -403,6 +407,9 @@ module.exports = class MerkleTree {
403407
}
404408

405409
get (index, error = true) {
410+
const c = this.cache.get(index)
411+
if (c) return c
412+
406413
let node = this.unflushed.get(index)
407414

408415
if (this.flushing !== null && node === undefined) {
@@ -422,7 +429,7 @@ module.exports = class MerkleTree {
422429
return Promise.resolve(node)
423430
}
424431

425-
return getStoredNode(this.storage, index, error)
432+
return getStoredNode(this.storage, index, this.cache, error)
426433
}
427434

428435
async flush () {
@@ -495,6 +502,7 @@ module.exports = class MerkleTree {
495502
}
496503

497504
clear () {
505+
this.cache = new Xache({ maxSize: this.cache.maxSize })
498506
this.truncated = true
499507
this.truncateTo = 0
500508
this.roots = []
@@ -754,7 +762,7 @@ module.exports = class MerkleTree {
754762

755763
const roots = []
756764
for (const index of flat.fullRoots(2 * length)) {
757-
roots.push(await getStoredNode(storage, index, true))
765+
roots.push(await getStoredNode(storage, index, null, true))
758766
}
759767

760768
return new MerkleTree(storage, roots, opts.fork || 0, opts.signature || null)
@@ -1085,7 +1093,7 @@ function blankNode (index) {
10851093

10861094
// Storage methods
10871095

1088-
function getStoredNode (storage, index, error) {
1096+
function getStoredNode (storage, index, cache, error) {
10891097
return new Promise((resolve, reject) => {
10901098
storage.read(40 * index, 40, (err, data) => {
10911099
if (err) {
@@ -1103,7 +1111,9 @@ function getStoredNode (storage, index, error) {
11031111
return
11041112
}
11051113

1106-
resolve({ index, size, hash })
1114+
const node = { index, size, hash }
1115+
if (cache !== null) cache.set(index, node)
1116+
resolve(node)
11071117
})
11081118
})
11091119
}
@@ -1122,7 +1132,7 @@ async function autoLength (storage) {
11221132
if (!nodes) return 0
11231133
const ite = flat.iterator(nodes - 1)
11241134
let index = nodes - 1
1125-
while (await getStoredNode(storage, ite.parent(), false)) index = ite.index
1135+
while (await getStoredNode(storage, ite.parent(), null, false)) index = ite.index
11261136
return flat.rightSpan(index) / 2 + 1
11271137
}
11281138

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"safety-catch": "^1.0.1",
4949
"sodium-universal": "^3.0.4",
5050
"streamx": "^2.12.4",
51-
"xache": "^1.0.0"
51+
"xache": "^1.1.0"
5252
},
5353
"devDependencies": {
5454
"brittle": "^2.0.0",

0 commit comments

Comments
 (0)