-
Notifications
You must be signed in to change notification settings - Fork 20.2k
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
p2p/dnsdisc: fix hot-spin when all trees are empty #22313
Conversation
In the random sync algorithm used by the DNS node iterator, we first pick a random tree and then perform one sync action on that tree. This happens in a loop until any node is found. If no trees contain any nodes, the iterator would just keep starting over in a hot loop, spinning at 100% CPU. The fix is a bit complicated. The iterator now checks if any sync action can be performed on the tree before selecting it. If no action can be performed on any tree, it waits for the closest root record recheck time to arrive and then tries again.
p2p/dnsdisc/client.go
Outdated
} | ||
|
||
// syncableTrees finds trees on which any meaningful sync action can be performed. | ||
func (it *randomIterator) syncableTrees() (syncable, disabled []*clientTree) { |
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.
I still want optimize this to reuse the same slices over and over, but let's review the basic idea first.
|
Adjusted the log message a bit:
|
Sorry, I ran the wrong code! |
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.
This seems to solve the issue 👍
if len(it.syncableList) > 0 { | ||
return true, it.syncableList | ||
} | ||
return false, it.disabledList |
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.
Maybe this totally doesn't matter (depends on how large the trees are?), but you could resize the unused one to zero here before returning
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.
At the moment, we only use one tree per client and I'm not worried about the memory usage. But will think about a way to avoid holding on to the trees in the future.
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.
Still LGTM, one question only
In the random sync algorithm used by the DNS node iterator, we first pick a random
tree and then perform one sync action on that tree. This happens in a loop until any
node is found. If no trees contain any nodes, the iterator will enter a hot loop spinning
at 100% CPU.
The fix is complicated. The iterator now checks if a meaningful sync action can
be performed on any tree. If there is nothing to do, it waits for the next root record
recheck time to arrive and then tries again.
Fixes #22306