mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
trie: polish the changes
This commit is contained in:
parent
46cac2ee07
commit
50ef3a2a54
3 changed files with 13 additions and 92 deletions
|
|
@ -18,7 +18,6 @@ package trie
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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
|
// commitChildren commits the children of the given fullnode
|
||||||
func (c *committer) commitChildren(path []byte, n *fullNode, parallel bool) ([17]node, []*wrapNode) {
|
func (c *committer) commitChildren(path []byte, n *fullNode, parallel bool) ([17]node, []*wrapNode) {
|
||||||
var (
|
var (
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
children [17]node
|
children [17]node
|
||||||
results [16][]*wrapNode
|
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++ {
|
for i := 0; i < 16; i++ {
|
||||||
child := n.Children[i]
|
child := n.Children[i]
|
||||||
if child == nil {
|
if child == nil {
|
||||||
|
|
@ -163,15 +139,14 @@ func (c *committer) commitChildren(path []byte, n *fullNode, parallel bool) ([17
|
||||||
if !parallel {
|
if !parallel {
|
||||||
children[i], results[i] = c.commit(append(path, byte(i)), child, false)
|
children[i], results[i] = c.commit(append(path, byte(i)), child, false)
|
||||||
} else {
|
} else {
|
||||||
tasks <- task{
|
wg.Add(1)
|
||||||
index: i,
|
go func(index int) {
|
||||||
node: child,
|
defer wg.Done()
|
||||||
path: append(path, byte(i)),
|
children[index], results[index] = c.commit(append(path, byte(index)), child, false)
|
||||||
}
|
}(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if parallel {
|
if parallel {
|
||||||
close(tasks)
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
// For the 17th child, it's possible the type is valuenode.
|
// 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),
|
path: string(path),
|
||||||
node: trienode.New(nhash, nodeToBytes(n)),
|
node: trienode.New(nhash, nodeToBytes(n)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the corresponding leaf node if it's required. We don't check
|
// 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
|
// full node since it's impossible to store value in fullNode. The key
|
||||||
// length of leaves should be exactly same..
|
// length of leaves should be exactly same..
|
||||||
|
|
@ -227,7 +201,6 @@ func (c *committer) store(path []byte, n node) (node, *wrapNode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash, wNode
|
return hash, wNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
27
trie/trie.go
27
trie/trie.go
|
|
@ -37,24 +37,13 @@ import (
|
||||||
//
|
//
|
||||||
// Trie is not safe for concurrent use.
|
// Trie is not safe for concurrent use.
|
||||||
type Trie struct {
|
type Trie struct {
|
||||||
root node
|
root node
|
||||||
owner common.Hash
|
owner common.Hash
|
||||||
|
committed bool // The Flag whether the commit operation is already performed
|
||||||
// Flag whether the commit operation is already performed. If so the
|
reader *trieReader // The handler trie can retrieve nodes from
|
||||||
// trie is not usable(latest states is invisible).
|
tracer *tracer // The tool to track the trie changes
|
||||||
committed bool
|
mutate int // The number of trie mutations that have been performed
|
||||||
|
hashed int // The number of mutations that have been hashed
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// newFlag returns the cache flag value for a newly created node.
|
// 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 {
|
func (t *Trie) update(key, value []byte) error {
|
||||||
t.mutate++
|
|
||||||
k := keybytesToHex(key)
|
k := keybytesToHex(key)
|
||||||
if len(value) != 0 {
|
if len(value) != 0 {
|
||||||
_, n, err := t.insert(t.root, nil, k, valueNode(value))
|
_, 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() {
|
for _, path := range t.tracer.deletedNodes() {
|
||||||
nodes.AddNode(path, trienode.NewDeleted())
|
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.root = newCommitter(nodes, t.tracer, collectLeaf, t.mutate > 100).Commit(t.root)
|
||||||
t.mutate = 0
|
t.mutate = 0
|
||||||
return rootHash, nodes
|
return rootHash, nodes
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/testrand"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"github.com/holiman/uint256"
|
"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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue