Commit 9b09c0fc authored by Martin Holst Swende's avatar Martin Holst Swende Committed by Péter Szilágyi

* trie: utilize callbacks instead of amassing lists in ref/unref (#20529)

* trie/tests: add benchmarks and update trie tests

* trie: update benchmark tests

* trie: utilize callbacks instead of amassing lists of hashes in database ref/unref

* trie: replace remaining non-callback based accesses
parent 770316dc
......@@ -180,35 +180,31 @@ func (n *cachedNode) obj(hash common.Hash) node {
return expandNode(hash[:], n.node)
}
// childs returns all the tracked children of this node, both the implicit ones
// from inside the node as well as the explicit ones from outside the node.
func (n *cachedNode) childs() []common.Hash {
children := make([]common.Hash, 0, 16)
// forChilds invokes the callback for all the tracked children of this node,
// both the implicit ones from inside the node as well as the explicit ones
//from outside the node.
func (n *cachedNode) forChilds(onChild func(hash common.Hash)) {
for child := range n.children {
children = append(children, child)
onChild(child)
}
if _, ok := n.node.(rawNode); !ok {
gatherChildren(n.node, &children)
forGatherChildren(n.node, onChild)
}
return children
}
// gatherChildren traverses the node hierarchy of a collapsed storage node and
// retrieves all the hashnode children.
func gatherChildren(n node, children *[]common.Hash) {
// forGatherChildren traverses the node hierarchy of a collapsed storage node and
// invokes the callback for all the hashnode children.
func forGatherChildren(n node, onChild func(hash common.Hash)) {
switch n := n.(type) {
case *rawShortNode:
gatherChildren(n.Val, children)
forGatherChildren(n.Val, onChild)
case rawFullNode:
for i := 0; i < 16; i++ {
gatherChildren(n[i], children)
forGatherChildren(n[i], onChild)
}
case hashNode:
*children = append(*children, common.BytesToHash(n))
onChild(common.BytesToHash(n))
case valueNode, nil:
default:
panic(fmt.Sprintf("unknown node type: %T", n))
}
......@@ -334,11 +330,11 @@ func (db *Database) insert(hash common.Hash, blob []byte, node node) {
size: uint16(len(blob)),
flushPrev: db.newest,
}
for _, child := range entry.childs() {
entry.forChilds(func(child common.Hash) {
if c := db.dirties[child]; c != nil {
c.parents++
}
}
})
db.dirties[hash] = entry
// Update the flush-list endpoints
......@@ -570,9 +566,9 @@ func (db *Database) dereference(child common.Hash, parent common.Hash) {
db.dirties[node.flushNext].flushPrev = node.flushPrev
}
// Dereference all children and delete the node
for _, hash := range node.childs() {
node.forChilds(func(hash common.Hash) {
db.dereference(hash, child)
}
})
delete(db.dirties, child)
db.dirtiesSize -= common.StorageSize(common.HashLength + int(node.size))
if node.children != nil {
......@@ -766,10 +762,14 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleane
if !ok {
return nil
}
for _, child := range node.childs() {
if err := db.commit(child, batch, uncacher); err != nil {
return err
var err error
node.forChilds(func(child common.Hash) {
if err == nil {
err = db.commit(child, batch, uncacher)
}
})
if err != nil {
return err
}
if err := batch.Put(hash[:], node.rlp()); err != nil {
return err
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment