-
Notifications
You must be signed in to change notification settings - Fork 674
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
merkledb
-- limit number of goroutines calculating node IDs
#1960
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5271bd7
remove unneeded return values resulting from calculateID
583bcbb
limit number of goroutines calculating node IDs
0c99ceb
remove comment
127f555
Merge branch 'merkledb-remove-unneeded-errors' into merkledb-limit-ca…
2574ae4
pass background context into semaphore acquire
d3889c6
change tracer level to debug for calculateNodeIDsHelper
fca21c1
don't release calculateNodeIDsSema until goroutine finishes
9691f07
Merge remote-tracking branch 'upstream/dev' into merkledb-limit-calcu…
c516040
fix comment
a26b631
int --> uint
07ff639
Merge branch 'dev' into merkledb-limit-calculation-goroutines
b1db447
remove span and context from calcualteNodeIDsHelper
151df7a
Merge branch 'merkledb-limit-calculation-goroutines' of github.com:av…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ import ( | |
oteltrace "go.opentelemetry.io/otel/trace" | ||
|
||
"golang.org/x/exp/slices" | ||
"golang.org/x/sync/errgroup" | ||
|
||
"github.com/ava-labs/avalanchego/database" | ||
"github.com/ava-labs/avalanchego/ids" | ||
|
@@ -213,6 +212,7 @@ func newHistoricalTrieView( | |
} | ||
|
||
// Recalculates the node IDs for all changed nodes in the trie. | ||
// Cancelling [ctx] doesn't cancel calculation. It's used only for tracing. | ||
func (t *trieView) calculateNodeIDs(ctx context.Context) error { | ||
var err error | ||
t.calculateNodesOnce.Do(func() { | ||
|
@@ -225,27 +225,25 @@ func (t *trieView) calculateNodeIDs(ctx context.Context) error { | |
// We wait to create the span until after checking that we need to actually | ||
// calculateNodeIDs to make traces more useful (otherwise there may be a span | ||
// per key modified even though IDs are not re-calculated). | ||
ctx, span := t.db.infoTracer.Start(ctx, "MerkleDB.trieview.calculateNodeIDs") | ||
_, span := t.db.infoTracer.Start(ctx, "MerkleDB.trieview.calculateNodeIDs") | ||
defer span.End() | ||
|
||
// add all the changed key/values to the nodes of the trie | ||
for key, change := range t.changes.values { | ||
if change.after.IsNothing() { | ||
// Note we're setting [err] defined outside this function. | ||
if err = t.remove(key); err != nil { | ||
return | ||
} | ||
// Note we're setting [err] defined outside this function. | ||
} else if _, err = t.insert(key, change.after); err != nil { | ||
return | ||
} | ||
} | ||
|
||
// [eg] limits the number of goroutines we start. | ||
var eg errgroup.Group | ||
eg.SetLimit(t.db.rootGenConcurrency) | ||
t.calculateNodeIDsHelper(ctx, t.root, &eg) | ||
if err = eg.Wait(); err != nil { | ||
return | ||
} | ||
_ = t.db.calculateNodeIDsSema.Acquire(context.Background(), 1) | ||
t.calculateNodeIDsHelper(t.root) | ||
t.db.calculateNodeIDsSema.Release(1) | ||
t.changes.rootID = t.root.id | ||
|
||
// ensure no ancestor changes occurred during execution | ||
|
@@ -259,18 +257,14 @@ func (t *trieView) calculateNodeIDs(ctx context.Context) error { | |
|
||
// Calculates the ID of all descendants of [n] which need to be recalculated, | ||
// and then calculates the ID of [n] itself. | ||
func (t *trieView) calculateNodeIDsHelper(ctx context.Context, n *node, eg *errgroup.Group) { | ||
func (t *trieView) calculateNodeIDsHelper(n *node) { | ||
var ( | ||
// We use [wg] to wait until all descendants of [n] have been updated. | ||
// Note we can't wait on [eg] because [eg] may have started goroutines | ||
// that aren't calculating IDs for descendants of [n]. | ||
wg sync.WaitGroup | ||
updatedChildren = make(chan *node, len(n.children)) | ||
) | ||
|
||
for childIndex, child := range n.children { | ||
childIndex, child := childIndex, child | ||
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. Don't think this was actually necessary |
||
|
||
childPath := n.key + path(childIndex) + child.compressedPath | ||
childNodeChange, ok := t.changes.nodes[childPath] | ||
if !ok { | ||
|
@@ -279,22 +273,24 @@ func (t *trieView) calculateNodeIDsHelper(ctx context.Context, n *node, eg *errg | |
} | ||
|
||
wg.Add(1) | ||
updateChild := func() { | ||
calculateChildID := func() { | ||
defer wg.Done() | ||
|
||
t.calculateNodeIDsHelper(ctx, childNodeChange.after, eg) | ||
t.calculateNodeIDsHelper(childNodeChange.after) | ||
|
||
// Note that this will never block | ||
updatedChildren <- childNodeChange.after | ||
} | ||
|
||
// Try updating the child and its descendants in a goroutine. | ||
if ok := eg.TryGo(func() error { | ||
updateChild() | ||
return nil | ||
}); !ok { | ||
if ok := t.db.calculateNodeIDsSema.TryAcquire(1); ok { | ||
go func() { | ||
calculateChildID() | ||
t.db.calculateNodeIDsSema.Release(1) | ||
}() | ||
} else { | ||
// We're at the goroutine limit; do the work in this goroutine. | ||
updateChild() | ||
calculateChildID() | ||
} | ||
} | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
is this to have the # of threads match the semaphore weight?
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.
Not sure I understand the question. In order for a new goroutine to run
calculateNodeIDsHelper
, it must acquire 1 from the semaphore and release that 1 when it exits the goroutine.