net: Optimize locator construction for "getblocks" messages #1880
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.
This caches the block locators used to ask for a range of blocks. Due to a sub-optimal workaround in our old net messaging code, a node will ask each peer that advertises a block for the next range. The node generates a subset of hashes from the current blockchain used as a locator for the block in the chain of the peer. Creating locators is extremely expensive—a node needs to scan the entire chain—so this PR adds a cache for the locators and reuses them if the node sends the same request. For nodes with many connections, this can dramatically improve the performance of the messaging system when it needs to respond to new blocks.
This optimization will become unnecessary when we backport newer chain and net messaging code from Bitcoin. For now, this cache can greatly improve a node's ability to serve a higher number of connections, and it reduces some CPU usage for non-listening nodes as well.
Here's the observed CPU usage of a VPS that serves almost 400 connections after applying the optimization on 09-11:
This should reduce the huge ping and latency spikes that I see on large listening nodes when a new block arrives (up to 60 seconds sometimes). The same problem causes the high CPU usage when synchronizing blocks near the chain tip. I'm working on a more general solution for that.