From 50ef3a2a54206fb191052b5b889b6233e3707c80 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Thu, 19 Sep 2024 11:24:15 +0800 Subject: [PATCH] trie: polish the changes --- trie/committer.go | 37 +++++-------------------------------- trie/trie.go | 27 ++++++++------------------- trie/trie_test.go | 41 ----------------------------------------- 3 files changed, 13 insertions(+), 92 deletions(-) diff --git a/trie/committer.go b/trie/committer.go index b853715a79..1d7b6fc5f0 100644 --- a/trie/committer.go +++ b/trie/committer.go @@ -18,7 +18,6 @@ package trie import ( "fmt" - "runtime" "sync" "github.com/ethereum/go-ethereum/common" @@ -115,36 +114,13 @@ func (c *committer) commit(path []byte, n node, topmost bool) (node, []*wrapNode } } -type task struct { - node node - index int - path []byte -} - // commitChildren commits the children of the given fullnode func (c *committer) commitChildren(path []byte, n *fullNode, parallel bool) ([17]node, []*wrapNode) { var ( wg sync.WaitGroup children [17]node results [16][]*wrapNode - tasks = make(chan task) ) - if parallel { - worker := func() { - defer wg.Done() - for t := range tasks { - children[t.index], results[t.index] = c.commit(t.path, t.node, false) - } - } - threads := runtime.NumCPU() - if threads > 16 { - threads = 16 - } - for i := 0; i < threads; i++ { - wg.Add(1) - go worker() - } - } for i := 0; i < 16; i++ { child := n.Children[i] if child == nil { @@ -163,15 +139,14 @@ func (c *committer) commitChildren(path []byte, n *fullNode, parallel bool) ([17 if !parallel { children[i], results[i] = c.commit(append(path, byte(i)), child, false) } else { - tasks <- task{ - index: i, - node: child, - path: append(path, byte(i)), - } + wg.Add(1) + go func(index int) { + defer wg.Done() + children[index], results[index] = c.commit(append(path, byte(index)), child, false) + }(i) } } if parallel { - close(tasks) wg.Wait() } // For the 17th child, it's possible the type is valuenode. @@ -215,7 +190,6 @@ func (c *committer) store(path []byte, n node) (node, *wrapNode) { path: string(path), node: trienode.New(nhash, nodeToBytes(n)), } - // Collect the corresponding leaf node if it's required. We don't check // full node since it's impossible to store value in fullNode. The key // length of leaves should be exactly same.. @@ -227,7 +201,6 @@ func (c *committer) store(path []byte, n node) (node, *wrapNode) { } } } - return hash, wNode } diff --git a/trie/trie.go b/trie/trie.go index b5613ee523..d263bc4cff 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -37,24 +37,13 @@ import ( // // Trie is not safe for concurrent use. type Trie struct { - root node - owner common.Hash - - // Flag whether the commit operation is already performed. If so the - // trie is not usable(latest states is invisible). - committed bool - - // reader is the handler trie can retrieve nodes from. - reader *trieReader - - // tracer is the tool to track the trie changes. - tracer *tracer - - // The number of trie mutations that have been performed - mutate int - - // The number of mutations that have been hashed - hashed int + root node + owner common.Hash + committed bool // The Flag whether the commit operation is already performed + reader *trieReader // The handler trie can retrieve nodes from + tracer *tracer // The tool to track the trie changes + mutate int // The number of trie mutations that have been performed + hashed int // The number of mutations that have been hashed } // newFlag returns the cache flag value for a newly created node. @@ -311,7 +300,6 @@ func (t *Trie) Update(key, value []byte) error { } func (t *Trie) update(key, value []byte) error { - t.mutate++ k := keybytesToHex(key) if len(value) != 0 { _, n, err := t.insert(t.root, nil, k, valueNode(value)) @@ -645,6 +633,7 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) { for _, path := range t.tracer.deletedNodes() { nodes.AddNode(path, trienode.NewDeleted()) } + // If the number of changes is below 100, we let one thread handle it t.root = newCommitter(nodes, t.tracer, collectLeaf, t.mutate > 100).Commit(t.root) t.mutate = 0 return rootHash, nodes diff --git a/trie/trie_test.go b/trie/trie_test.go index d7e2b8ac59..505b517bc5 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/testrand" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie/trienode" "github.com/holiman/uint256" @@ -1207,43 +1206,3 @@ func FuzzTrie(f *testing.F) { } }) } - -func BenchmarkCommit(b *testing.B) { - benchmarkCommit(b, 500) - benchmarkCommit(b, 1000) - benchmarkCommit(b, 2000) - benchmarkCommit(b, 5000) -} - -func benchmarkCommit(b *testing.B, n int) { - b.Run(fmt.Sprintf("commit-%vnodes-single", n), func(b *testing.B) { - testCommit(b, n, false) - }) - - b.Run(fmt.Sprintf("commit-%vnodes-parallel", n), func(b *testing.B) { - testCommit(b, n, true) - }) -} - -func testCommit(b *testing.B, n int, parallel bool) { - // test 10 times to get a better average - N := 10 - tries := make([]*Trie, N) - for i := 0; i < N; i++ { - tries[i] = NewEmpty(nil) - for j := 0; j < n; j++ { - key := testrand.Bytes(32) - val := testrand.Bytes(32) - tries[i].Update(key, val) - } - tries[i].Hash() - if !parallel { - tries[i].mutate = 0 - } - } - - b.ResetTimer() - for i := 0; i < 10; i++ { - tries[i].Commit(true) - } -}