mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
wip: ignore this, and squash it
This commit is contained in:
parent
c28a51e465
commit
5524fcb63a
2 changed files with 55 additions and 1 deletions
|
|
@ -17,6 +17,7 @@
|
|||
package trie
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"sync"
|
||||
|
||||
|
|
@ -169,6 +170,37 @@ func (h *hasher) hashChildren(original node, db *Database) (node, node, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// estimateSize estimates the size of an rlp-encoded node, without actually
|
||||
// rlp-encoding it (zero allocs). This method has been experimentally tried, and with a trie
|
||||
// with 1000 leafs, the only errors above 1% are on small shortnodes, where this
|
||||
// method overestimates by 2 or 3 bytes (e.g. 37 instead of 35)
|
||||
func estimateSize(n node) int {
|
||||
switch n := n.(type) {
|
||||
case *shortNode:
|
||||
// A short node contains a compacted key, and a value.
|
||||
return 3 + len(n.Key) + estimateSize(n.Val)
|
||||
case *fullNode:
|
||||
// A full node contains up to 16 hashes (some nils), and a key
|
||||
s := 3
|
||||
for i := 0; i < 16; i++ {
|
||||
if child := n.Children[i]; child != nil {
|
||||
s += estimateSize(child)
|
||||
} else {
|
||||
s += 1
|
||||
}
|
||||
}
|
||||
return s
|
||||
case valueNode:
|
||||
return 1 + len(n)
|
||||
case hashNode:
|
||||
return 1 + len(n)
|
||||
default:
|
||||
panic(fmt.Sprintf("node type %T", n))
|
||||
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// store hashes the node n and if we have a storage layer specified, it writes
|
||||
// the key/value pair to it and tracks any node->child references as well as any
|
||||
// node->external trie references.
|
||||
|
|
@ -190,6 +222,16 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
|
|||
if hash == nil {
|
||||
hash = h.makeHashNode(h.tmp)
|
||||
}
|
||||
// DEBUG todo remove me
|
||||
// When we already have a cached hash, there's no need to rlp-encode the
|
||||
// blob -- however, we stil need to use report the size to the database.
|
||||
//actual := len(h.tmp)
|
||||
//got := estimateSize(n)
|
||||
//diff := math.Abs(1.0-float64(got)/float64(actual)) * 100
|
||||
//if diff > 1.0 {
|
||||
// fmt.Printf("actual: %d, got %d, diff : %02f%% (%T)\n", actual, got, diff, n)
|
||||
//}
|
||||
|
||||
// If we're using channel-based leaf-reporting, send to channel.
|
||||
// The leaf channel will be active only when there an active leaf-callback
|
||||
if h.leafCh != nil {
|
||||
|
|
|
|||
|
|
@ -568,6 +568,18 @@ func benchmarkCommitAfterHash(b *testing.B, onleaf LeafCallback) {
|
|||
trie.Commit(onleaf)
|
||||
}
|
||||
|
||||
func TestCommitAfterHash(t *testing.T) {
|
||||
// Create a realistic account trie to hash
|
||||
addresses, accounts := makeAccounts(1000)
|
||||
trie := newEmpty()
|
||||
for i := 0; i < len(addresses); i++ {
|
||||
trie.Update(crypto.Keccak256(addresses[i][:]), accounts[i])
|
||||
}
|
||||
// Insert the accounts into the trie and hash it
|
||||
trie.Hash()
|
||||
trie.Commit(nil)
|
||||
}
|
||||
|
||||
func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
|
||||
// Make the random benchmark deterministic
|
||||
random := rand.New(rand.NewSource(0))
|
||||
|
|
@ -637,7 +649,7 @@ func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accou
|
|||
// Insert the accounts into the trie and hash it
|
||||
trie.Hash()
|
||||
b.StartTimer()
|
||||
trie.Commit()
|
||||
trie.Commit(nil)
|
||||
b.StopTimer()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue