From a7a8999a33a328b38a2681c9163a5b598db4d5cb Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 15 Feb 2016 20:30:36 -0800 Subject: [PATCH] more lru cache. --- lib/bcoin/blockdb.js | 9 +-- lib/bcoin/chaindb.js | 2 +- lib/bcoin/lru.js | 136 ++++++++++++++++++++++++------------------- lib/bcoin/ramdisk.js | 16 +++++ 4 files changed, 97 insertions(+), 66 deletions(-) diff --git a/lib/bcoin/blockdb.js b/lib/bcoin/blockdb.js index 120bf8aa..41753c2f 100644 --- a/lib/bcoin/blockdb.js +++ b/lib/bcoin/blockdb.js @@ -414,10 +414,11 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call var parts = data.key.split('/').slice(3); var hash = parts[0]; var index = +parts[1]; + var id = hash + '/' + index; var record = self.parseOffset(data.value); pending++; - if (self.unspentCache.has(hash + '/' + index)) { - coins.push(self.unspentCache.get(hash + '/' + index)); + if (self.unspentCache.has(id)) { + coins.push(self.unspentCache.get(id)); pending--; if (done) { if (!pending) @@ -446,7 +447,7 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call value: data.value, spent: false }); - self.unspentCache.set(hash + '/' + index, coin); + self.unspentCache.set(id, coin); coins.push(coin); } @@ -715,7 +716,7 @@ function BlockData(options) { BlockData.prototype._init = function _init() { if (!bcoin.fs) { utils.debug('`fs` module not available. Falling back to ramdisk.'); - this.ramdisk = bcoin.ramdisk(new Buffer([]), 40 * 1024 * 1024); + this.ramdisk = new bcoin.ramdisk(40 * 1024 * 1024); return; } diff --git a/lib/bcoin/chaindb.js b/lib/bcoin/chaindb.js index f2a468b3..c3b6b702 100644 --- a/lib/bcoin/chaindb.js +++ b/lib/bcoin/chaindb.js @@ -58,7 +58,7 @@ function ChainDB(chain, options) { ChainDB.prototype._init = function _init() { if (!bcoin.fs) { utils.debug('`fs` module not available. Falling back to ramdisk.'); - this.ramdisk = bcoin.ramdisk(new Buffer([]), 40 * 1024 * 1024); + this.ramdisk = new bcoin.ramdisk(40 * 1024 * 1024); return; } diff --git a/lib/bcoin/lru.js b/lib/bcoin/lru.js index 73825ec2..b50c300e 100644 --- a/lib/bcoin/lru.js +++ b/lib/bcoin/lru.js @@ -23,23 +23,31 @@ function LRU(maxSize) { this.tail = null; } -LRU.prototype._getSize = function _getSize(value) { - if (value == null) - return 1; +LRU.prototype._getSize = function _getSize(item) { + var keySize = item.key.length * 2; - if (typeof value === 'number') - return 4; + if (item.value == null) + return keySize + 1; - if (value._raw) - return value._raw.length; + if (typeof item.value === 'number') + return keySize + 4; - if (value.getSize) - return value.getSize(); + if (item.value._raw) + return keySize + item.value._raw.length; - if (typeof value.length === 'number') - return value.length; + if (item.value.getSize) + return keySize + item.value.getSize(); - return 1; + if (typeof item.value._size === 'number') + return keySize + item.value._size; + + if (typeof item.value === 'string') + return keySize + item.value.length * 2; + + if (typeof item.value.length === 'number') + return keySize + item.value.length; + + return keySize + 1; }; LRU.prototype._compact = function _compact() { @@ -49,31 +57,21 @@ LRU.prototype._compact = function _compact() { return; for (item = this.head; item; item = item.next) { - // if (this.size <= this.maxSize / 2 | 0) if (this.size < this.maxSize) break; - this.size -= this._getSize(item.value); - delete this.data[item.key]; + this.remove(item.key); } - - if (!item) { - this.head = null; - this.tail = null; - return; - } - - this.head = item; - item.prev = null; }; LRU.prototype.set = function set(key, value) { var item = this.data[key]; + if (item) { - this.size -= this._getSize(item.value); - this.size += this._getSize(value); + this.size -= this._getSize(item); item.value = value; - this._remove(item); - this._append(item); + this.size += this._getSize(item); + this._removeList(item); + this._appendList(item); this._compact(); return; } @@ -82,22 +80,21 @@ LRU.prototype.set = function set(key, value) { this.data[key] = item; - this._append(item); + this._appendList(item); - this.size += this._getSize(value); + this.size += this._getSize(item); this._compact(); }; LRU.prototype.get = function get(key) { var item = this.data[key]; - var prev, next, tail; if (!item) return; - this._remove(item); - this._append(item); + this._removeList(item); + this._appendList(item); return item.value; }; @@ -108,29 +105,28 @@ LRU.prototype.has = function get(key) { LRU.prototype.remove = function remove(key) { var item = this.data[key]; - var prev, next; if (!item) return false; - this.size -= this._getSize(item.value); + this.size -= this._getSize(item); delete this.data[key]; - this._remove(item); + this._removeList(item); return true; }; -LRU.prototype._prepend = function prepend(item) { - this._insert(null, item); +LRU.prototype._prependList = function prependList(item) { + this._insertList(null, item); }; -LRU.prototype._append = function prepend(item) { - this._insert(this.tail, item); +LRU.prototype._appendList = function appendList(item) { + this._insertList(this.tail, item); }; -LRU.prototype._insert = function insert(ref, item) { +LRU.prototype._insertList = function insertList(ref, item) { assert(!item.next); assert(!item.prev); if (ref == null) { @@ -151,18 +147,18 @@ LRU.prototype._insert = function insert(ref, item) { this.tail = item; }; -LRU.prototype._remove = function insert(item) { +LRU.prototype._removeList = function removeList(item) { if (item.prev) item.prev.next = item.next; if (item.next) item.next.prev = item.prev; - if (this.head === item) + if (item === this.head) this.head = item.next; - if (this.tail === item) - this.tail = item.prev; + if (item == this.tail) + this.tail = item.prev || this.head; item.prev = null; item.next = null; @@ -188,44 +184,62 @@ var a2 = '2'; var a3 = '3'; var a4 = '4'; var a5 = '5'; -var lru = new LRU(5); +var a6 = '6'; +var lru = new LRU(((2 * 4) + 4) * 2); lru.set('a1', a1); assert(lru.get('a1') === '1'); -assert(lru.size === 1); +assert(lru.size === ((2 * 1) + 1) * 2); assert(lru.head.key === 'a1' && lru.tail.key === 'a1' && !lru.head.prev && !lru.head.next); -console.log(lru._keys()); +lru._keys(); +// console.log(lru._keys()); lru.set('a2', a2); assert(lru.get('a2') === '2'); -assert(lru.size === 2); +assert(lru.size === ((2 * 2) + 2) * 2); assert(lru.head.key === 'a1' && lru.tail.key === 'a2' && !lru.head.prev && lru.head.next.key === 'a2' && !lru.tail.next && lru.tail.prev.key === 'a1'); -console.log(lru._keys()); +lru._keys(); +// console.log(lru._keys()); lru.set('a3', a3); assert(lru.get('a3') === '3'); -assert(lru.size === 3); -console.log(lru._keys()); +assert(lru.size === ((2 * 3) + 3) * 2); +lru._keys(); +// console.log(lru._keys()); lru.set('a3', a3); assert(lru.get('a3') === '3'); -assert(lru.size === 3); -console.log(lru._keys()); +assert(lru.size === ((2 * 3) + 3) * 2); +lru._keys(); +// console.log(lru._keys()); lru.set('a4', a4); assert(lru.get('a4') === '4'); -assert(lru.size === 4); -console.log(lru._keys()); -// lru.set('a5', a5); -// assert(lru.get('a5') === '5'); -// assert(lru.size === 4); -// assert(!lru.get('a1')); +assert(lru.size === ((2 * 4) + 4) * 2); +lru._keys(); +// console.log(lru._keys()); assert(lru.get('a1')); lru.remove('a1'); -console.log(lru._keys()); +lru._keys(); +// console.log(lru._keys()); var _a3 = lru.head.next; assert(_a3.key === 'a3'); assert(_a3.prev === lru.head && _a3.next === lru.tail); assert(lru.head.key === 'a2' && lru.tail.key === 'a4' && !lru.head.prev && lru.head.next.key === 'a3' && !lru.tail.next && lru.tail.prev.key === 'a3'); +lru.set('a5', a5); +assert(lru.get('a5') === '5'); +assert(lru.size === ((2 * 4) + 4) * 2); +assert(!lru.get('a1')); +lru._keys(); +// console.log(lru._keys()); +lru.get('a2'); +lru._keys(); +// console.log(lru._keys()); +lru.set('a6', a6); +assert(lru.get('a6') === '6'); +assert(lru.size === ((2 * 4) + 4) * 2); +assert(!lru.get('a3')); +lru._keys(); +// console.log(lru._keys()); /** * Expose diff --git a/lib/bcoin/ramdisk.js b/lib/bcoin/ramdisk.js index 10415a9f..d35d9c7d 100644 --- a/lib/bcoin/ramdisk.js +++ b/lib/bcoin/ramdisk.js @@ -4,10 +4,26 @@ * https://github.com/indutny/bcoin */ +var bcoin = require('../bcoin'); +var utils = bcoin.utils; +var assert = utils.assert; + +/** + * Ramdisk + */ + function Ramdisk(fileData, size) { if (!(this instanceof Ramdisk)) return new Ramdisk(fileData, size); + if (size == null) { + size = fileData; + fileData = new Buffer([]); + } + + assert(Buffer.isBuffer(fileData)); + assert(typeof size === 'number'); + if (size < fileData.length) size = fileData.length + (fileData.length / 2 | 0);