lru cache
This commit is contained in:
parent
8f897c256b
commit
2ae8c17398
@ -43,6 +43,7 @@ bcoin.ecdsa.signature = require('elliptic/lib/elliptic/ec/signature');
|
||||
bcoin.ecdsa.keypair = require('elliptic/lib/elliptic/ec/key');
|
||||
|
||||
bcoin.utils = require('./bcoin/utils');
|
||||
bcoin.lru = require('./bcoin/lru');
|
||||
bcoin.protocol = require('./bcoin/protocol');
|
||||
bcoin.bloom = require('./bcoin/bloom');
|
||||
bcoin.script = require('./bcoin/script');
|
||||
|
||||
@ -38,6 +38,8 @@ function BlockDB(options) {
|
||||
this.parser = new bcoin.protocol.parser();
|
||||
|
||||
this.data = new BlockData();
|
||||
this.unspentCache = new bcoin.lru(32 * 1024 * 1024);
|
||||
this.txCache = new bcoin.lru(32 * 1024 * 1024);
|
||||
|
||||
this.index = new levelup(this.file, {
|
||||
keyEncoding: 'ascii',
|
||||
@ -414,6 +416,15 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call
|
||||
var index = +parts[1];
|
||||
var record = self.parseOffset(data.value);
|
||||
pending++;
|
||||
if (self.unspentCache.has(hash + '/' + index)) {
|
||||
coins.push(self.unspentCache.get(hash + '/' + index));
|
||||
pending--;
|
||||
if (done) {
|
||||
if (!pending)
|
||||
return callback(null, coins);
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.data.getAsync(record.size, record.offset, function(err, data) {
|
||||
var coin;
|
||||
|
||||
@ -435,6 +446,7 @@ BlockDB.prototype._getCoinsByAddress = function _getCoinsByAddress(address, call
|
||||
value: data.value,
|
||||
spent: false
|
||||
});
|
||||
self.unspentCache.set(hash + '/' + index, coin);
|
||||
coins.push(coin);
|
||||
}
|
||||
|
||||
@ -543,14 +555,24 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback)
|
||||
});
|
||||
|
||||
stream.on('data', function(data) {
|
||||
// var parts = data.key.split('/').slice(3);
|
||||
// var hash = parts[0];
|
||||
var parts = data.key.split('/').slice(3);
|
||||
var hash = parts[0];
|
||||
// Could store block hash in key
|
||||
// var blockHash = parts[1];
|
||||
var record = self.parseOffset(data.value);
|
||||
|
||||
pending++;
|
||||
|
||||
if (self.txCache.has(hash)) {
|
||||
coins.push(self.txCache.get(hash));
|
||||
pending--;
|
||||
if (done) {
|
||||
if (!pending)
|
||||
return callback(null, coins);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self.data.getAsync(record.size, record.offset, function(err, data) {
|
||||
var tx, entry;
|
||||
|
||||
@ -568,6 +590,7 @@ BlockDB.prototype._getTXByAddress = function _getTXByAddress(address, callback)
|
||||
tx.height = record.height;
|
||||
tx.ts = entry.ts;
|
||||
tx.block = entry.hash;
|
||||
self.txCache.set(hash, tx);
|
||||
txs.push(tx);
|
||||
}
|
||||
|
||||
|
||||
@ -74,6 +74,10 @@ Coin.prototype.__defineGetter__('chain', function() {
|
||||
return this._chain || bcoin.chain.global;
|
||||
});
|
||||
|
||||
Coin.prototype.getSize = function getSize() {
|
||||
return 4 + 4 + 8 + bcoin.script.getSize(this.script) + 32 + 4 + 1;
|
||||
};
|
||||
|
||||
Coin.prototype.getConfirmations = function getConfirmations(height) {
|
||||
var top;
|
||||
|
||||
|
||||
157
lib/bcoin/lru.js
Normal file
157
lib/bcoin/lru.js
Normal file
@ -0,0 +1,157 @@
|
||||
/**
|
||||
* lru.js - LRU cache for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* https://github.com/indutny/bcoin
|
||||
*/
|
||||
|
||||
function LRU(maxSize) {
|
||||
if (!(this instanceof LRU))
|
||||
return new LRU(maxSize);
|
||||
|
||||
this.data = {};
|
||||
this.size = 0;
|
||||
this.maxSize = maxSize;
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
}
|
||||
|
||||
LRU.prototype._getSize = function _getSize(value) {
|
||||
if (value == null)
|
||||
return 1;
|
||||
|
||||
if (typeof value === 'number')
|
||||
return 4;
|
||||
|
||||
if (value._raw)
|
||||
return value._raw.length;
|
||||
|
||||
if (value.getSize)
|
||||
return value.getSize();
|
||||
|
||||
if (typeof value.length === 'number')
|
||||
return value.length;
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
LRU.prototype._compact = function _compact() {
|
||||
var item;
|
||||
|
||||
if (this.size < this.maxSize)
|
||||
return;
|
||||
|
||||
for (item = this.head; item; item = item.next) {
|
||||
if (this.size <= this.maxSize / 2 | 0)
|
||||
break;
|
||||
this.size -= this._getSize(item.value);
|
||||
delete this.data[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);
|
||||
item.value = value;
|
||||
this.get(key);
|
||||
this._compact();
|
||||
return;
|
||||
}
|
||||
|
||||
item = { key: key, value: value };
|
||||
|
||||
this.data[key] = item;
|
||||
|
||||
if (!this.head) {
|
||||
this.head = item;
|
||||
this.tail = item;
|
||||
} else {
|
||||
this.tail.next = item;
|
||||
item.prev = this.tail;
|
||||
this.tail = item;
|
||||
}
|
||||
|
||||
this.size += this._getSize(value);
|
||||
|
||||
this._compact();
|
||||
};
|
||||
|
||||
LRU.prototype.get = function get(key) {
|
||||
var item = this.data[key];
|
||||
var prev, next, tail;
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (this.tail === item)
|
||||
return item.value;
|
||||
|
||||
prev = item.prev;
|
||||
next = item.next;
|
||||
tail = this.tail;
|
||||
|
||||
this.tail = item;
|
||||
|
||||
if (this.head === item)
|
||||
this.head = next || item;
|
||||
|
||||
if (prev)
|
||||
prev.next = next;
|
||||
|
||||
if (next)
|
||||
next.prev = prev;
|
||||
|
||||
item.next = null;
|
||||
item.prev = tail;
|
||||
|
||||
return item.value;
|
||||
};
|
||||
|
||||
LRU.prototype.has = function get(key) {
|
||||
return this.data[key] != null;
|
||||
};
|
||||
|
||||
LRU.prototype.remove = function remove(key) {
|
||||
var item = this.data[key];
|
||||
var prev, next;
|
||||
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
this.size -= this._getSize(item.value);
|
||||
|
||||
delete this.data[key];
|
||||
|
||||
prev = item.prev;
|
||||
next = item.next;
|
||||
|
||||
if (prev)
|
||||
prev.next = next;
|
||||
|
||||
if (next)
|
||||
next.prev = prev;
|
||||
|
||||
if (this.tail === item)
|
||||
this.tail = prev || null;
|
||||
|
||||
if (this.head === item)
|
||||
this.head = next || null;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
module.exports = LRU;
|
||||
Loading…
Reference in New Issue
Block a user