Browse Source

Skip GET_BLOCK_SUMMARIES requests if it can already be fulfilled entirely from the peer's chain tip block summaries cache.

Loading from the cache should speed up sync decisions, particularly when choose which peer to sync from. The greater the number of connected peers, the more significant this optimization will be. It should also reduce wasted network requests and data usage.

Adding this check prior to making a network request is a simple way to introduce the new cached summaries from BLOCK_SUMMARIES_V2 without having to rewrite a lot of the complex sync / peer comparison logic. Longer term we may want to rewrite that logic to read from the cache directly, but it doesn't make sense to introduce that level of risk at this point time, especially as the Synchronizer may be rewritten soon to prefer longer chains.

Even so, this is still quite a high risk commit so lots of testing will be needed.
pull/97/head
CalDescent 2 years ago
parent
commit
8cedf618f4
  1. 35
      src/main/java/org/qortal/controller/Synchronizer.java

35
src/main/java/org/qortal/controller/Synchronizer.java

@ -8,6 +8,7 @@ import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -1556,7 +1557,41 @@ public class Synchronizer extends Thread {
return SynchronizationResult.OK;
}
private List<BlockSummaryData> getBlockSummariesFromCache(Peer peer, byte[] parentSignature, int numberRequested) {
List<BlockSummaryData> peerSummaries = peer.getChainTipSummaries();
if (peerSummaries == null)
return null;
// Check if the requested parent block exists in peer's summaries cache
int parentIndex = IntStream.range(0, peerSummaries.size()).filter(i -> Arrays.equals(peerSummaries.get(i).getSignature(), parentSignature)).findFirst().orElse(-1);
if (parentIndex < 0)
return null;
// Peer's summaries contains the requested parent, so return summaries after that
// Make sure we have at least one block after the parent block
int summariesAvailable = peerSummaries.size() - parentIndex - 1;
if (summariesAvailable <= 0)
return null;
// Don't try and return more summaries than we have, or more than were requested
int summariesToReturn = Math.min(numberRequested, summariesAvailable);
int startIndex = parentIndex + 1;
int endIndex = startIndex + summariesToReturn - 1;
if (endIndex > peerSummaries.size() - 1)
return null;
LOGGER.trace("Serving {} block summaries from cache", summariesToReturn);
return peerSummaries.subList(startIndex, endIndex);
}
private List<BlockSummaryData> getBlockSummaries(Peer peer, byte[] parentSignature, int numberRequested) throws InterruptedException {
// We might be able to shortcut the response if we already have the summaries in the peer's chain tip data
List<BlockSummaryData> cachedSummaries = this.getBlockSummariesFromCache(peer, parentSignature, numberRequested);
if (cachedSummaries != null && !cachedSummaries.isEmpty())
return cachedSummaries;
LOGGER.trace("Requesting {} block summaries from peer {}", numberRequested, peer);
Message getBlockSummariesMessage = new GetBlockSummariesMessage(parentSignature, numberRequested);
Message message = peer.getResponse(getBlockSummariesMessage);

Loading…
Cancel
Save