Added a block cache to speed up syncing.
This commit is contained in:
parent
cb06d8a3cb
commit
ad650c383e
@ -29,6 +29,7 @@ var BlockService = function(options) {
|
|||||||
this._blocksInQueue = 0;
|
this._blocksInQueue = 0;
|
||||||
this._recentBlockHashesCount = options.recentBlockHashesCount || 50; // if you expect this chain to reorg deeper than 50, set this
|
this._recentBlockHashesCount = options.recentBlockHashesCount || 50; // if you expect this chain to reorg deeper than 50, set this
|
||||||
this._recentBlockHashes = new LRU(this._recentBlockHashesCount);
|
this._recentBlockHashes = new LRU(this._recentBlockHashesCount);
|
||||||
|
this._readAheadBlockCount = options.readAheadBlockCount || 2; // this is the number of blocks to direct the p2p service to read aheead
|
||||||
};
|
};
|
||||||
|
|
||||||
inherits(BlockService, BaseService);
|
inherits(BlockService, BaseService);
|
||||||
@ -943,13 +944,13 @@ BlockService.prototype._sync = function() {
|
|||||||
|
|
||||||
log.debug('Block Service: querying header service for next block using tip: ' + self._tip.hash);
|
log.debug('Block Service: querying header service for next block using tip: ' + self._tip.hash);
|
||||||
|
|
||||||
self._header.getNextHash(self._tip, function(err, targetHash, nextHash) {
|
self._header.getEndHash(self._tip, self._readAheadBlockCount, function(err, targetHash, endHash) {
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
return self._handleError(err);
|
return self._handleError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetHash && !nextHash) {
|
if (!targetHash && !endHash) {
|
||||||
return self.emit('synced');
|
return self.emit('synced');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,7 +975,7 @@ BlockService.prototype._sync = function() {
|
|||||||
self._p2p.getP2PBlock({
|
self._p2p.getP2PBlock({
|
||||||
filter: {
|
filter: {
|
||||||
startHash: self._tip.hash,
|
startHash: self._tip.hash,
|
||||||
endHash: nextHash
|
endHash: endHash
|
||||||
},
|
},
|
||||||
blockHash: targetHash
|
blockHash: targetHash
|
||||||
}, self._syncBlock.bind(self));
|
}, self._syncBlock.bind(self));
|
||||||
|
|||||||
@ -852,12 +852,13 @@ HeaderService.prototype._sync = function() {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// this gets the header that is +2 places from hash or returns 0 if there is no such
|
HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
||||||
HeaderService.prototype.getNextHash = function(tip, callback) {
|
|
||||||
|
assert(blockCount >= 1, 'Header Service: block count to getEndHash must be at least 1.');
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var numResultsNeeded = Math.min((self._tip.height - tip.height), 2);
|
var numResultsNeeded = Math.min((self._tip.height - tip.height), blockCount + 1);
|
||||||
|
|
||||||
if (numResultsNeeded === 0 && self._tip.hash === tip.hash) {
|
if (numResultsNeeded === 0 && self._tip.hash === tip.hash) {
|
||||||
return callback();
|
return callback();
|
||||||
@ -867,14 +868,14 @@ HeaderService.prototype.getNextHash = function(tip, callback) {
|
|||||||
return callback(new Error('Header Service: block service is mis-aligned '));
|
return callback(new Error('Header Service: block service is mis-aligned '));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var startingHeight = tip.height + 1;
|
||||||
var start = self._encoding.encodeHeaderHeightKey(tip.height + 1);
|
var start = self._encoding.encodeHeaderHeightKey(startingHeight);
|
||||||
var end = self._encoding.encodeHeaderHeightKey(tip.height + 3);
|
var end = self._encoding.encodeHeaderHeightKey(startingHeight + blockCount);
|
||||||
var results = [];
|
var results = [];
|
||||||
|
|
||||||
var criteria = {
|
var criteria = {
|
||||||
gte: start,
|
gte: start,
|
||||||
lt: end
|
lte: end
|
||||||
};
|
};
|
||||||
|
|
||||||
var stream = self._db.createReadStream(criteria);
|
var stream = self._db.createReadStream(criteria);
|
||||||
@ -895,19 +896,18 @@ HeaderService.prototype.getNextHash = function(tip, callback) {
|
|||||||
return streamErr;
|
return streamErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(results.length === numResultsNeeded, 'GetNextHash returned incorrect number of results.');
|
assert(results.length === numResultsNeeded, 'getEndHash returned incorrect number of results.');
|
||||||
|
|
||||||
if (!results[1]) {
|
var index = numResultsNeeded - 1;
|
||||||
results[1] = 0;
|
var endHash = index <= 0 || !results[index] ? 0 : results[index];
|
||||||
}
|
|
||||||
|
|
||||||
if (self._slowMode) {
|
if (self._slowMode) {
|
||||||
return setTimeout(function() {
|
return setTimeout(function() {
|
||||||
callback(null, results[0], results[1]);
|
callback(null, results[0], endHash);
|
||||||
}, self._slowMode);
|
}, self._slowMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null, results[0], results[1]);
|
callback(null, results[0], endHash);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,10 @@ var P2P = function(options) {
|
|||||||
this._currentBestHeight = null;
|
this._currentBestHeight = null;
|
||||||
this._latestBits = 0x1d00ffff;
|
this._latestBits = 0x1d00ffff;
|
||||||
this._outgoingTxs = LRU(100); // these are outgoing txs that are awaiting getdata messages
|
this._outgoingTxs = LRU(100); // these are outgoing txs that are awaiting getdata messages
|
||||||
|
this._blockCache = options.blockCacheCount || LRU({
|
||||||
|
max: 10,
|
||||||
|
maxAge: 1000 * 60 * 5}); // keep this modest to avoid memory dumps [hash -> block]
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
util.inherits(P2P, BaseService);
|
util.inherits(P2P, BaseService);
|
||||||
@ -53,8 +57,18 @@ P2P.prototype.getNumberOfPeers = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
P2P.prototype.getP2PBlock = function(opts, callback) {
|
P2P.prototype.getP2PBlock = function(opts, callback) {
|
||||||
|
|
||||||
// opts is { filter: {<start and end hashes>}, blockHash: block hash we want }
|
// opts is { filter: {<start and end hashes>}, blockHash: block hash we want }
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
// do we already have this block in our cache?
|
||||||
|
var block = self._blockCache.get(opts.blockHash);
|
||||||
|
|
||||||
|
if (block) {
|
||||||
|
return callback(block);
|
||||||
|
}
|
||||||
|
|
||||||
var peer = self._getPeer();
|
var peer = self._getPeer();
|
||||||
|
|
||||||
var blockFilter = self._setResourceFilter(opts.filter, 'blocks');
|
var blockFilter = self._setResourceFilter(opts.filter, 'blocks');
|
||||||
@ -291,6 +305,7 @@ P2P.prototype._initPubSub = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
P2P.prototype._onPeerBlock = function(peer, message) {
|
P2P.prototype._onPeerBlock = function(peer, message) {
|
||||||
|
this._blockCache.set(message.block.rhash(), message.block);
|
||||||
this.emit(message.block.rhash(), message.block);
|
this.emit(message.block.rhash(), message.block);
|
||||||
this._broadcast(this.subscriptions.block, 'p2p/block', message.block);
|
this._broadcast(this.subscriptions.block, 'p2p/block', message.block);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user