mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
Merge 48fe6f3bb1 into d48e6ae66f
This commit is contained in:
commit
91a17cafe3
6 changed files with 23 additions and 19 deletions
|
|
@ -44,7 +44,7 @@ const (
|
||||||
maxPastTries = 12
|
maxPastTries = 12
|
||||||
|
|
||||||
// Trie cache generation limit.
|
// Trie cache generation limit.
|
||||||
maxTrieCacheGen = 120
|
maxTrieCacheGen = 10000
|
||||||
|
|
||||||
// Number of codehash->size associations to keep.
|
// Number of codehash->size associations to keep.
|
||||||
codeSizeCacheSize = 100000
|
codeSizeCacheSize = 100000
|
||||||
|
|
|
||||||
|
|
@ -49,15 +49,20 @@ func returnHasherToPool(h *hasher) {
|
||||||
hasherPool.Put(h)
|
hasherPool.Put(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// canUnload decides whether a node can be unloaded.
|
||||||
|
func (n *nodeFlag) canUnload(cachegen, cachelimit uint16, depth int) bool {
|
||||||
|
return !n.dirty && cachegen-n.gen >= cachelimit/uint16(depth+1)
|
||||||
|
}
|
||||||
|
|
||||||
// hash collapses a node down into a hash node, also returning a copy of the
|
// hash collapses a node down into a hash node, also returning a copy of the
|
||||||
// original node initialzied with the computed hash to replace the original one.
|
// original node initialzied with the computed hash to replace the original one.
|
||||||
func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error) {
|
func (h *hasher) hash(n node, db DatabaseWriter, force bool, depth int) (node, node, error) {
|
||||||
// If we're not storing the node, just hashing, use avaialble cached data
|
// If we're not storing the node, just hashing, use avaialble cached data
|
||||||
if hash, dirty := n.cache(); hash != nil {
|
if hash, dirty := n.cache(); hash != nil {
|
||||||
if db == nil {
|
if db == nil {
|
||||||
return hash, n, nil
|
return hash, n, nil
|
||||||
}
|
}
|
||||||
if n.canUnload(h.cachegen, h.cachelimit) {
|
if n.canUnload(h.cachegen, h.cachelimit, depth) {
|
||||||
// Unload the node from cache. All of its subnodes will have a lower or equal
|
// Unload the node from cache. All of its subnodes will have a lower or equal
|
||||||
// cache generation number.
|
// cache generation number.
|
||||||
return hash, hash, nil
|
return hash, hash, nil
|
||||||
|
|
@ -67,7 +72,7 @@ func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Trie not processed yet or needs storage, walk the children
|
// Trie not processed yet or needs storage, walk the children
|
||||||
collapsed, cached, err := h.hashChildren(n, db)
|
collapsed, cached, err := h.hashChildren(n, db, depth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hashNode{}, n, err
|
return hashNode{}, n, err
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +102,7 @@ func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error)
|
||||||
// hashChildren replaces the children of a node with their hashes if the encoded
|
// hashChildren replaces the children of a node with their hashes if the encoded
|
||||||
// size of the child is larger than a hash, returning the collapsed node as well
|
// size of the child is larger than a hash, returning the collapsed node as well
|
||||||
// as a replacement for the original node with the child hashes cached in.
|
// as a replacement for the original node with the child hashes cached in.
|
||||||
func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, error) {
|
func (h *hasher) hashChildren(original node, db DatabaseWriter, depth int) (node, node, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
switch n := original.(type) {
|
switch n := original.(type) {
|
||||||
|
|
@ -108,7 +113,7 @@ func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, err
|
||||||
cached.Key = common.CopyBytes(n.Key)
|
cached.Key = common.CopyBytes(n.Key)
|
||||||
|
|
||||||
if _, ok := n.Val.(valueNode); !ok {
|
if _, ok := n.Val.(valueNode); !ok {
|
||||||
collapsed.Val, cached.Val, err = h.hash(n.Val, db, false)
|
collapsed.Val, cached.Val, err = h.hash(n.Val, db, false, depth+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return original, original, err
|
return original, original, err
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +129,7 @@ func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, err
|
||||||
|
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
if n.Children[i] != nil {
|
if n.Children[i] != nil {
|
||||||
collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false)
|
collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false, depth+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return original, original, err
|
return original, original, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
trie/node.go
17
trie/node.go
|
|
@ -30,7 +30,7 @@ var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b
|
||||||
type node interface {
|
type node interface {
|
||||||
fstring(string) string
|
fstring(string) string
|
||||||
cache() (hashNode, bool)
|
cache() (hashNode, bool)
|
||||||
canUnload(cachegen, cachelimit uint16) bool
|
canUnload(cachegen, cachelimit uint16, depth int) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
@ -62,15 +62,14 @@ type nodeFlag struct {
|
||||||
dirty bool // whether the node has changes that must be written to the database
|
dirty bool // whether the node has changes that must be written to the database
|
||||||
}
|
}
|
||||||
|
|
||||||
// canUnload tells whether a node can be unloaded.
|
func (n *fullNode) canUnload(gen, limit uint16, depth int) bool {
|
||||||
func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool {
|
return n.flags.canUnload(gen, limit, depth)
|
||||||
return !n.dirty && cachegen-n.gen >= cachelimit
|
|
||||||
}
|
}
|
||||||
|
func (n *shortNode) canUnload(gen, limit uint16, depth int) bool {
|
||||||
func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
return n.flags.canUnload(gen, limit, depth)
|
||||||
func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) }
|
}
|
||||||
func (n hashNode) canUnload(uint16, uint16) bool { return false }
|
func (n hashNode) canUnload(uint16, uint16, int) bool { return false }
|
||||||
func (n valueNode) canUnload(uint16, uint16) bool { return false }
|
func (n valueNode) canUnload(uint16, uint16, int) bool { return false }
|
||||||
|
|
||||||
func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
|
func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
|
||||||
func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
|
func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty }
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func TestCanUnload(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
if got := test.flag.canUnload(test.cachegen, test.cachelimit); got != test.want {
|
if got := test.flag.canUnload(test.cachegen, test.cachelimit, 0); got != test.want {
|
||||||
t.Errorf("%+v\n got %t, want %t", test, got, test.want)
|
t.Errorf("%+v\n got %t, want %t", test, got, test.want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ func (t *Trie) Prove(key []byte) []rlp.RawValue {
|
||||||
for i, n := range nodes {
|
for i, n := range nodes {
|
||||||
// Don't bother checking for errors here since hasher panics
|
// Don't bother checking for errors here since hasher panics
|
||||||
// if encoding doesn't work and we're not writing to any database.
|
// if encoding doesn't work and we're not writing to any database.
|
||||||
n, _, _ = hasher.hashChildren(n, nil)
|
n, _, _ = hasher.hashChildren(n, nil, 0)
|
||||||
hn, _ := hasher.store(n, nil, false)
|
hn, _ := hasher.store(n, nil, false)
|
||||||
if _, ok := hn.(hashNode); ok || i == 0 {
|
if _, ok := hn.(hashNode); ok || i == 0 {
|
||||||
// If the node's database encoding is a hash (or is the
|
// If the node's database encoding is a hash (or is the
|
||||||
|
|
|
||||||
|
|
@ -493,5 +493,5 @@ func (t *Trie) hashRoot(db DatabaseWriter) (node, node, error) {
|
||||||
}
|
}
|
||||||
h := newHasher(t.cachegen, t.cachelimit)
|
h := newHasher(t.cachegen, t.cachelimit)
|
||||||
defer returnHasherToPool(h)
|
defer returnHasherToPool(h)
|
||||||
return h.hash(t.root, db, true)
|
return h.hash(t.root, db, true, 0)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue