mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
trie: make db insert use size instead of full data, update tests
This commit is contained in:
parent
2a9d1e7067
commit
7cc9b10ed6
3 changed files with 30 additions and 10 deletions
|
|
@ -314,24 +314,24 @@ func (db *Database) InsertBlob(hash common.Hash, blob []byte) {
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
defer db.lock.Unlock()
|
defer db.lock.Unlock()
|
||||||
|
|
||||||
db.insert(hash, blob, rawNode(blob))
|
db.insert(hash, len(blob), rawNode(blob))
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert inserts a collapsed trie node into the memory database. This method is
|
// insert inserts a collapsed trie node into the memory database. This method is
|
||||||
// a more generic version of InsertBlob, supporting both raw blob insertions as
|
// a more generic version of InsertBlob, supporting both raw blob insertions as
|
||||||
// well ex trie node insertions. The blob must always be specified to allow proper
|
// well ex trie node insertions. The blob size must be specified to allow proper
|
||||||
// size tracking.
|
// size tracking.
|
||||||
func (db *Database) insert(hash common.Hash, blob []byte, node node) {
|
func (db *Database) insert(hash common.Hash, size int, node node) {
|
||||||
// If the node's already cached, skip
|
// If the node's already cached, skip
|
||||||
if _, ok := db.dirties[hash]; ok {
|
if _, ok := db.dirties[hash]; ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
memcacheDirtyWriteMeter.Mark(int64(len(blob)))
|
memcacheDirtyWriteMeter.Mark(int64(size))
|
||||||
|
|
||||||
// Create the cached entry for this node
|
// Create the cached entry for this node
|
||||||
entry := &cachedNode{
|
entry := &cachedNode{
|
||||||
node: simplifyNode(node),
|
node: simplifyNode(node),
|
||||||
size: uint16(len(blob)),
|
size: uint16(size),
|
||||||
flushPrev: db.newest,
|
flushPrev: db.newest,
|
||||||
}
|
}
|
||||||
for _, child := range entry.childs() {
|
for _, child := range entry.childs() {
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
||||||
hash := common.BytesToHash(hash)
|
hash := common.BytesToHash(hash)
|
||||||
|
|
||||||
db.lock.Lock()
|
db.lock.Lock()
|
||||||
db.insert(hash, h.tmp, n)
|
db.insert(hash, len(h.tmp), n)
|
||||||
db.lock.Unlock()
|
db.lock.Unlock()
|
||||||
|
|
||||||
// Track external references from account->storage trie
|
// Track external references from account->storage trie
|
||||||
|
|
|
||||||
|
|
@ -512,14 +512,34 @@ func BenchmarkHash(b *testing.B) {
|
||||||
trie.Hash()
|
trie.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type account struct {
|
||||||
|
Nonce uint64
|
||||||
|
Balance *big.Int
|
||||||
|
Root common.Hash
|
||||||
|
Code []byte
|
||||||
|
}
|
||||||
|
|
||||||
// Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
|
// Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
|
||||||
// we cannot use b.N as the number of hashing rouns, since all rounds apart from
|
// we cannot use b.N as the number of hashing rouns, since all rounds apart from
|
||||||
// the first one will be NOOP. As such, we'll use b.N as the number of account to
|
// the first one will be NOOP. As such, we'll use b.N as the number of account to
|
||||||
// insert into the trie before measuring the hashing.
|
// insert into the trie before measuring the hashing.
|
||||||
func BenchmarkCommitAfterHash(b *testing.B) {
|
func BenchmarkCommitAfterHash(b *testing.B) {
|
||||||
|
b.Run("no-onleaf", func(b *testing.B) {
|
||||||
|
benchmarkCommitAfterHash(b, nil)
|
||||||
|
})
|
||||||
|
onleaf := func(leaf []byte, parent common.Hash) error {
|
||||||
|
var a account
|
||||||
|
rlp.DecodeBytes(leaf, &a)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b.Run("with-onleaf", func(b *testing.B) {
|
||||||
|
benchmarkCommitAfterHash(b, onleaf)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkCommitAfterHash(b *testing.B, onleaf LeafCallback) {
|
||||||
// Make the random benchmark deterministic
|
// Make the random benchmark deterministic
|
||||||
random := rand.New(rand.NewSource(0))
|
random := rand.New(rand.NewSource(0))
|
||||||
|
|
||||||
// Create a realistic account trie to hash
|
// Create a realistic account trie to hash
|
||||||
addresses := make([][20]byte, b.N)
|
addresses := make([][20]byte, b.N)
|
||||||
for i := 0; i < len(addresses); i++ {
|
for i := 0; i < len(addresses); i++ {
|
||||||
|
|
@ -535,17 +555,17 @@ func BenchmarkCommitAfterHash(b *testing.B) {
|
||||||
root = emptyRoot
|
root = emptyRoot
|
||||||
code = crypto.Keccak256(nil)
|
code = crypto.Keccak256(nil)
|
||||||
)
|
)
|
||||||
accounts[i], _ = rlp.EncodeToBytes([]interface{}{nonce, balance, root, code})
|
accounts[i], _ = rlp.EncodeToBytes(&account{nonce, balance, root, code})
|
||||||
}
|
}
|
||||||
// Insert the accounts into the trie and hash it
|
|
||||||
trie := newEmpty()
|
trie := newEmpty()
|
||||||
for i := 0; i < len(addresses); i++ {
|
for i := 0; i < len(addresses); i++ {
|
||||||
trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
|
trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
|
||||||
}
|
}
|
||||||
|
// Insert the accounts into the trie and hash it
|
||||||
trie.Hash()
|
trie.Hash()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
trie.Commit(nil)
|
trie.Commit(onleaf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tempDB() (string, *Database) {
|
func tempDB() (string, *Database) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue