From a9c116c98c87ecb41ca1d6fd2721d95432e9e3d3 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 24 Feb 2016 23:55:41 -0800 Subject: [PATCH] profiler. refactoring. --- lib/bcoin/abstractblock.js | 32 ------------------ lib/bcoin/chain.js | 15 +++++++-- lib/bcoin/compactblock.js | 12 +------ lib/bcoin/profiler.js | 67 ++++++++++++++++++++------------------ lib/bcoin/utils.js | 41 +++++++++++++++++++++-- 5 files changed, 86 insertions(+), 81 deletions(-) diff --git a/lib/bcoin/abstractblock.js b/lib/bcoin/abstractblock.js index dcdffe89..416860b3 100644 --- a/lib/bcoin/abstractblock.js +++ b/lib/bcoin/abstractblock.js @@ -47,38 +47,6 @@ function AbstractBlock(data) { this.lowVersion = this.version & 7; } -AbstractBlock.prototype.getMerkleBranch = function getMerkleBranch(index) { - var tree = utils.buildMerkleTree(this.merkleRoot); - var branch = []; - var j = 0; - for (var size = this.totalTX; size > 1; size = (size + 1) / 2 | 0) { - var i = Math.min(index ^ 1, size - 1); - branch.push(tree[j + i]); - index >>= 1; - j += size; - } - return branch; -}; - -AbstractBlock.prototype.hasMerkleItem = function hasMerkleItem(hash, branch, index) { - if (index === -1) - return false; - - if (typeof hash === 'string') - hash = new Buffer(hash, 'hex'); - - for (var i = 0; i < branch.length; i++) { - var otherside = branch[i]; - if (index & 1) - hash = utils.dsha256(Buffer.concat([otherside, hash])); - else - hash = utils.dsha256(Buffer.concat([hash, otherside])); - index >>= 1; - } - - return utils.toHex(hash) === this.merkleRoot; -}; - AbstractBlock.prototype.hash = function hash(enc) { if (!this._hash) this._hash = utils.dsha256(this.abbr()); diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 515f5e8a..08416839 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -1172,9 +1172,14 @@ Chain.prototype.add = function add(initial, peer, callback, force) { // validated, and emitted. Hopefully the deserialized // blocks get cleaned up by the GC quickly. if (block.type === 'compactblock') { - block = block.toBlock(peer); - if (!block) - return done(new Error('Failed to parse block.')); + try { + block = block.toBlock(); + } catch (e) { + // Ugly hack to handle + // the error properly. + peer.parser.emit('error', e); + return done(e); + } } // Do "contextual" verification on our block @@ -1326,6 +1331,10 @@ Chain.prototype.add = function add(initial, peer, callback, force) { // Keep track of total blocks handled. self.total += total; + // Take heap snapshot for debugging. + if (self.total % 10 === 0) + bcoin.profiler.snapshot(); + // We intentionally did not asyncify the // callback so if it calls chain.add, it // still gets added to the queue. The diff --git a/lib/bcoin/compactblock.js b/lib/bcoin/compactblock.js index d7f45c81..d2098d07 100644 --- a/lib/bcoin/compactblock.js +++ b/lib/bcoin/compactblock.js @@ -38,17 +38,7 @@ CompactBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() { }; CompactBlock.prototype.toBlock = function toBlock(peer) { - var block; - - // XXX Hack - try { - block = bcoin.protocol.parser.parseBlock(this._raw); - } catch (e) { - peer.parser.emit('error', e); - return; - } - - return new bcoin.block(block); + return new bcoin.block(bcoin.protocol.parser.parseBlock(this._raw)); }; /** diff --git a/lib/bcoin/profiler.js b/lib/bcoin/profiler.js index ef5a224d..c1022960 100644 --- a/lib/bcoin/profiler.js +++ b/lib/bcoin/profiler.js @@ -13,38 +13,43 @@ var profiler; if (bcoin.profile && !bcoin.isBrowser) profiler = require('v8-' + 'profiler'); +if (profiler) { + utils.nextTick(function() { + utils.debug('Starting node with profiler enabled.'); + }); +} + /** * Profile */ function Profile(name) { if (profiler) { - if (!name) - name = ''; - name += '-' + Profile.uid++; + name = 'profile-' + (name ? name + '-' : '') + Profile.uid++; this.profile = profiler.startProfiling(name, true); this.name = name; + utils.debug('Starting CPU profile: %s', this.name); } } Profile.uid = 0; -Profile.prototype.stopProfiling = function stopProfiling(callback) { +Profile.prototype.stopProfiling = function stopProfiling() { if (!profiler) return; assert(this.profile); - this.profile.stopProfiling(); + return this.profile.stopProfiling(); }; -Profile.prototype.del = function del(callback) { +Profile.prototype.del = function del() { if (!profiler) return; assert(this.profile); - this.profile['delete'](); + return this.profile['delete'](); }; Profile.prototype.save = function save(callback) { @@ -57,22 +62,20 @@ Profile.prototype.save = function save(callback) { assert(this.profile); - this.profile['export'](function(err, result) { + utils.debug('Saving CPU profile: %s', this.name); + + return this.profile['export'](function(err, result) { var file; - if (err) { - self.profile['delete'](); - delete self.profile; + self.profile['delete'](); + delete self.profile; + + if (err) return callback(err); - } - file = bcoin.prefix + '/profile-' + self.name + '.json'; + file = bcoin.prefix + '/' + self.name + '.cpuprofile'; - fs.writeFile(file, result, function(err) { - self.profile['delete'](); - delete self.profile; - callback(err); - }); + fs.writeFile(file, result, callback); }); }; @@ -82,11 +85,10 @@ Profile.prototype.save = function save(callback) { function Snapshot(name) { if (profiler) { - if (!name) - name = ''; - name += '-' + Snapshot.uid++; + name = 'snapshot-' + (name ? name + '-' : '') + Snapshot.uid++; this.snapshot = profiler.takeSnapshot(name); this.name = name; + utils.debug('Taking heap snapshot: %s', this.name); } } @@ -129,22 +131,20 @@ Snapshot.prototype.save = function save(callback) { assert(this.snapshot); - this.snapshot['export'](function(err, result) { + utils.debug('Saving heap snapshot: %s', this.name); + + return this.snapshot['export'](function(err, result) { var file; - if (err) { - self.profile['delete'](); - delete self.profile; + self.snapshot['delete'](); + delete self.snapshot; + + if (err) return callback(err); - } - file = bcoin.prefix + '/snapshot-' + self.name + '.json'; + file = bcoin.prefix + '/' + self.name + '.heapsnapshot'; - fs.writeFile(file, result, function(err) { - self.snapshot['delete'](); - delete self.snapshot; - callback(err); - }); + fs.writeFile(file, result, callback); }); }; @@ -168,6 +168,9 @@ exports.snapshot = function snapshot(name, callback) { name = null; } + if (!profiler) + return callback ? utils.nextTick(callback) : null; + snapshot = new Snapshot(name); snapshot.save(callback); }; diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 912a7aa0..60337f43 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -1628,7 +1628,42 @@ utils.getMerkleRoot = function getMerkleRoot(items) { return tree[tree.length - 1]; }; -// Hook into bn here to ensure we get a toBuffer() method. -bn.prototype.toBuffer = function toBuffer(order, size) { - return new Buffer(this.toArray(order, size)); +utils.getMerkleBranch = function getMerkleBranch(index, hashes) { + var tree = utils.buildMerkleTree(hashes); + var branch = []; + var size = this.totalTX; + var j = 0; + var i; + + for (; size > 1; size = (size + 1) / 2 | 0) { + i = Math.min(index ^ 1, size - 1); + branch.push(tree[j + i]); + index >>= 1; + j += size; + } + + return branch; +}; + +utils.checkMerkleBranch = function checkMerkleBranch(hash, branch, index) { + var otherside, i; + + if (index === -1) + return false; + + if (typeof hash === 'string') + hash = new Buffer(hash, 'hex'); + + for (i = 0; i < branch.length; i++) { + otherside = branch[i]; + + if (index & 1) + hash = utils.dsha256(Buffer.concat([otherside, hash])); + else + hash = utils.dsha256(Buffer.concat([hash, otherside])); + + index >>= 1; + } + + return hash; };