-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[EN Performance] Optimize checkpoint serialization for -37GB operational RAM, -2.7 minutes duration, -19.6 million allocs (50% fewer allocs) #3050
Changes from all commits
3be56c5
9bc441c
28331ac
b88da42
14b7303
d136a3e
20f3022
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ package flattener | |
import ( | ||
"github.com/onflow/flow-go/ledger" | ||
"github.com/onflow/flow-go/ledger/complete/mtrie/node" | ||
"github.com/onflow/flow-go/ledger/complete/mtrie/trie" | ||
) | ||
|
||
// NodeIterator is an iterator over the nodes in a trie. | ||
|
@@ -76,13 +75,13 @@ type NodeIterator struct { | |
// as for each node, the children have been previously encountered. | ||
// NodeIterator created by NewNodeIterator is safe for concurrent use | ||
// because visitedNodes is always nil in this case. | ||
func NewNodeIterator(mTrie *trie.MTrie) *NodeIterator { | ||
func NewNodeIterator(n *node.Node) *NodeIterator { | ||
// for a Trie with height H (measured by number of edges), the longest possible path contains H+1 vertices | ||
stackSize := ledger.NodeMaxHeight + 1 | ||
i := &NodeIterator{ | ||
stack: make([]*node.Node, 0, stackSize), | ||
} | ||
i.unprocessedRoot = mTrie.RootNode() | ||
i.unprocessedRoot = n | ||
return i | ||
} | ||
|
||
|
@@ -98,15 +97,15 @@ func NewNodeIterator(mTrie *trie.MTrie) *NodeIterator { | |
// When re-building the Trie from the sequence of nodes, one can build the trie on the fly, | ||
// as for each node, the children have been previously encountered. | ||
// WARNING: visitedNodes is not safe for concurrent use. | ||
func NewUniqueNodeIterator(mTrie *trie.MTrie, visitedNodes map[*node.Node]uint64) *NodeIterator { | ||
func NewUniqueNodeIterator(n *node.Node, visitedNodes map[*node.Node]uint64) *NodeIterator { | ||
// For a Trie with height H (measured by number of edges), the longest possible path | ||
// contains H+1 vertices. | ||
stackSize := ledger.NodeMaxHeight + 1 | ||
i := &NodeIterator{ | ||
stack: make([]*node.Node, 0, stackSize), | ||
visitedNodes: visitedNodes, | ||
} | ||
i.unprocessedRoot = mTrie.RootNode() | ||
i.unprocessedRoot = n | ||
return i | ||
} | ||
|
||
|
@@ -115,7 +114,7 @@ func (i *NodeIterator) Next() bool { | |
// initial call to Next() for a non-empty trie | ||
i.dig(i.unprocessedRoot) | ||
i.unprocessedRoot = nil | ||
return true | ||
return len(i.stack) > 0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we change this? It seems like an important change, but I don't see why we would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bug fix for a problem that didn't surface yet because of the way node iterator was used. The bug is unique node iterator's This bug doesn't happen when we iterate nodes of an entire trie (root nodes are always unique). In this PR, we iterate nodes of subtries and subtries can be shared and visited already. So instead of always returning There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the explanation! It does make sense. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Test for this bug is already in iterator_test.go#L269-L396. The test iterates 3 left substries and 3 right subtries (some subtries are shared). The test verifies that:
|
||
} | ||
|
||
// the current head of the stack, `n`, has been recalled | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for fixing this node iterator to be a proper node iterator.