From a92dae21d6c7d5fc277c1905fcc53469f784c0c6 Mon Sep 17 00:00:00 2001 From: Matthew Halpern Date: Thu, 28 Mar 2019 09:23:28 -0700 Subject: [PATCH] [BENCHMARK] trie: prioritize trie sync nodes by depth and lexigraphic key ordering --- trie/sync.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/trie/sync.go b/trie/sync.go index 85f1b0f850..44a9147c04 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -17,8 +17,10 @@ package trie import ( + "encoding/binary" "errors" "fmt" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/prque" @@ -46,6 +48,23 @@ type request struct { callback LeafCallback // Callback to invoke if a leaf node it reached on this branch } +// priority returns the request priority in the trie scheduler. +func (r *request) priority() int64 { + // Priority is meant to sort requests according to their depth and + // lexigraphic ordering within LevelDB, so that they can be retrieved + // from peers more efficiently and also stored more efficiently. + prefix := binary.BigEndian.Uint64(r.hash[:8]) + // The prefix is inverted so that keys with a lower lexigraphic ordering + // have a larger number than keys with a higher lexigraphic ordering. + invertedPrefix := uint64(math.MaxUint64) - prefix + // Priority format: depth[:8] || invertedPrefix[:7] + // Note: the maximum number of nodes from the account state trie root to any + // account storage trie leaf is 128, which fits into a signed byte + // (with zero indexing) + priority := uint64(r.depth) << 56 | invertedPrefix >> 8 + return int64(priority) +} + // SyncResult is a simple list to return missing nodes along with their request // hashes. type SyncResult struct { @@ -242,7 +261,7 @@ func (s *Sync) schedule(req *request) { return } // Schedule the request for future retrieval - s.queue.Push(req.hash, int64(req.depth)) + s.queue.Push(req.hash, req.priority()) s.requests[req.hash] = req }