trie: use chan-based commit only when leaf-callback is present

This commit is contained in:
Martin Holst Swende 2019-12-18 09:41:13 +01:00
parent 3c8ec1b569
commit c28a51e465
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 25 additions and 9 deletions

View file

@ -70,10 +70,15 @@ var hasherPool = sync.Pool{
func newHasher(onleaf LeafCallback) *hasher { func newHasher(onleaf LeafCallback) *hasher {
h := hasherPool.Get().(*hasher) h := hasherPool.Get().(*hasher)
h.onleaf = onleaf h.onleaf = onleaf
if onleaf != nil {
h.leafCh = make(chan *Leaf, 200) // arbitrary number
}
return h return h
} }
func returnHasherToPool(h *hasher) { func returnHasherToPool(h *hasher) {
h.onleaf = nil
h.leafCh = nil
hasherPool.Put(h) hasherPool.Put(h)
} }
@ -185,12 +190,21 @@ func (h *hasher) store(n node, db *Database, force bool) (node, error) {
if hash == nil { if hash == nil {
hash = h.makeHashNode(h.tmp) hash = h.makeHashNode(h.tmp)
} }
if db != nil { // 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 {
h.leafCh <- &Leaf{ h.leafCh <- &Leaf{
size: len(h.tmp), size: len(h.tmp),
hash: common.BytesToHash(hash), hash: common.BytesToHash(hash),
node: n, node: n,
} }
} else if db != nil {
// No leaf-callback used, but there's still a database. Do serial
// insertion
db.lock.Lock()
db.insert(common.BytesToHash(hash), len(h.tmp), n)
db.lock.Unlock()
} }
return hash, nil return hash, nil
} }

View file

@ -420,14 +420,17 @@ func (t *Trie) Commit(onleaf LeafCallback) (root common.Hash, err error) {
return emptyRoot, nil return emptyRoot, nil
} }
h := newHasher(onleaf) h := newHasher(onleaf)
h.leafCh = make(chan *Leaf, 200) // arbitrary number
defer returnHasherToPool(h) defer returnHasherToPool(h)
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) if onleaf != nil {
go h.commitLoop(t.db, &wg) wg.Add(1)
hash, cached, err := h.hash(t.root, t.db, true) go h.commitLoop(t.db, &wg)
close(h.leafCh) }
wg.Wait() hash, cached, err := h.hash(t.root, t.db, true)
if onleaf != nil {
close(h.leafCh)
wg.Wait()
}
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -443,4 +446,3 @@ func (t *Trie) hashRoot(db *Database, onleaf LeafCallback) (node, node, error) {
defer returnHasherToPool(h) defer returnHasherToPool(h)
return h.hash(t.root, db, true) return h.hash(t.root, db, true)
} }

View file

@ -637,7 +637,7 @@ func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accou
// Insert the accounts into the trie and hash it // Insert the accounts into the trie and hash it
trie.Hash() trie.Hash()
b.StartTimer() b.StartTimer()
trie.Commit(nil) trie.Commit()
b.StopTimer() b.StopTimer()
} }