aboutsummaryrefslogtreecommitdiffstats
path: root/trie/hasher.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2018-06-21 17:28:05 +0800
committerFelix Lange <fjl@users.noreply.github.com>2018-06-21 17:28:05 +0800
commitd926bf2c7e3182d694c15829a37a0ca7331cd03c (patch)
treec2d3ddd85941a231fb05de46c36703273d11814a /trie/hasher.go
parent8db8d074e2fff547e9d85169018e03f89b5975a1 (diff)
downloaddexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar.gz
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar.bz2
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar.lz
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar.xz
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.tar.zst
dexon-d926bf2c7e3182d694c15829a37a0ca7331cd03c.zip
trie: cache collapsed tries node, not rlp blobs (#16876)
The current trie memory database/cache that we do pruning on stores trie nodes as binary rlp encoded blobs, and also stores the node relationships/references for GC purposes. However, most of the trie nodes (everything apart from a value node) is in essence just a collection of references. This PR switches out the RLP encoded trie blobs with the collapsed-but-not-serialized trie nodes. This permits most of the references to be recovered from within the node data structure, avoiding the need to track them a second time (expensive memory wise).
Diffstat (limited to 'trie/hasher.go')
-rw-r--r--trie/hasher.go30
1 files changed, 5 insertions, 25 deletions
diff --git a/trie/hasher.go b/trie/hasher.go
index 47c6dd8f9..7b1d7793f 100644
--- a/trie/hasher.go
+++ b/trie/hasher.go
@@ -137,9 +137,6 @@ func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
return original, original, err
}
}
- if collapsed.Val == nil {
- collapsed.Val = valueNode(nil) // Ensure that nil children are encoded as empty strings.
- }
return collapsed, cached, nil
case *fullNode:
@@ -152,14 +149,9 @@ func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
if err != nil {
return original, original, err
}
- } else {
- collapsed.Children[i] = valueNode(nil) // Ensure that nil children are encoded as empty strings.
}
}
cached.Children[16] = n.Children[16]
- if collapsed.Children[16] == nil {
- collapsed.Children[16] = valueNode(nil)
- }
return collapsed, cached, nil
default:
@@ -192,34 +184,22 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
if db != nil {
// We are pooling the trie nodes into an intermediate memory cache
- db.lock.Lock()
hash := common.BytesToHash(hash)
- db.insert(hash, h.tmp)
- // Track all direct parent->child node references
- switch n := n.(type) {
- case *shortNode:
- if child, ok := n.Val.(hashNode); ok {
- db.reference(common.BytesToHash(child), hash)
- }
- case *fullNode:
- for i := 0; i < 16; i++ {
- if child, ok := n.Children[i].(hashNode); ok {
- db.reference(common.BytesToHash(child), hash)
- }
- }
- }
+
+ db.lock.Lock()
+ db.insert(hash, h.tmp, n)
db.lock.Unlock()
// Track external references from account->storage trie
if h.onleaf != nil {
switch n := n.(type) {
case *shortNode:
- if child, ok := n.Val.(valueNode); ok && child != nil {
+ if child, ok := n.Val.(valueNode); ok {
h.onleaf(child, hash)
}
case *fullNode:
for i := 0; i < 16; i++ {
- if child, ok := n.Children[i].(valueNode); ok && child != nil {
+ if child, ok := n.Children[i].(valueNode); ok {
h.onleaf(child, hash)
}
}