lru cache
This commit is contained in:
parent
2ae8c17398
commit
3bfd276b76
167
lib/bcoin/lru.js
167
lib/bcoin/lru.js
@ -4,6 +4,14 @@
|
|||||||
* https://github.com/indutny/bcoin
|
* https://github.com/indutny/bcoin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var bcoin = require('../bcoin');
|
||||||
|
var utils = bcoin.utils;
|
||||||
|
var assert = utils.assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LRU
|
||||||
|
*/
|
||||||
|
|
||||||
function LRU(maxSize) {
|
function LRU(maxSize) {
|
||||||
if (!(this instanceof LRU))
|
if (!(this instanceof LRU))
|
||||||
return new LRU(maxSize);
|
return new LRU(maxSize);
|
||||||
@ -37,11 +45,12 @@ LRU.prototype._getSize = function _getSize(value) {
|
|||||||
LRU.prototype._compact = function _compact() {
|
LRU.prototype._compact = function _compact() {
|
||||||
var item;
|
var item;
|
||||||
|
|
||||||
if (this.size < this.maxSize)
|
if (this.size <= this.maxSize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (item = this.head; item; item = item.next) {
|
for (item = this.head; item; item = item.next) {
|
||||||
if (this.size <= this.maxSize / 2 | 0)
|
// if (this.size <= this.maxSize / 2 | 0)
|
||||||
|
if (this.size < this.maxSize)
|
||||||
break;
|
break;
|
||||||
this.size -= this._getSize(item.value);
|
this.size -= this._getSize(item.value);
|
||||||
delete this.data[item.key];
|
delete this.data[item.key];
|
||||||
@ -63,7 +72,8 @@ LRU.prototype.set = function set(key, value) {
|
|||||||
this.size -= this._getSize(item.value);
|
this.size -= this._getSize(item.value);
|
||||||
this.size += this._getSize(value);
|
this.size += this._getSize(value);
|
||||||
item.value = value;
|
item.value = value;
|
||||||
this.get(key);
|
this._remove(item);
|
||||||
|
this._append(item);
|
||||||
this._compact();
|
this._compact();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -72,14 +82,7 @@ LRU.prototype.set = function set(key, value) {
|
|||||||
|
|
||||||
this.data[key] = item;
|
this.data[key] = item;
|
||||||
|
|
||||||
if (!this.head) {
|
this._append(item);
|
||||||
this.head = item;
|
|
||||||
this.tail = item;
|
|
||||||
} else {
|
|
||||||
this.tail.next = item;
|
|
||||||
item.prev = this.tail;
|
|
||||||
this.tail = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.size += this._getSize(value);
|
this.size += this._getSize(value);
|
||||||
|
|
||||||
@ -93,26 +96,8 @@ LRU.prototype.get = function get(key) {
|
|||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.tail === item)
|
this._remove(item);
|
||||||
return item.value;
|
this._append(item);
|
||||||
|
|
||||||
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;
|
return item.value;
|
||||||
};
|
};
|
||||||
@ -132,24 +117,116 @@ LRU.prototype.remove = function remove(key) {
|
|||||||
|
|
||||||
delete this.data[key];
|
delete this.data[key];
|
||||||
|
|
||||||
prev = item.prev;
|
this._remove(item);
|
||||||
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;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LRU.prototype._prepend = function prepend(item) {
|
||||||
|
this._insert(null, item);
|
||||||
|
};
|
||||||
|
|
||||||
|
LRU.prototype._append = function prepend(item) {
|
||||||
|
this._insert(this.tail, item);
|
||||||
|
};
|
||||||
|
|
||||||
|
LRU.prototype._insert = function insert(ref, item) {
|
||||||
|
assert(!item.next);
|
||||||
|
assert(!item.prev);
|
||||||
|
if (ref == null) {
|
||||||
|
if (!this.head) {
|
||||||
|
this.head = item;
|
||||||
|
this.tail = item;
|
||||||
|
} else {
|
||||||
|
this.head.prev = item;
|
||||||
|
item.next = this.head;
|
||||||
|
this.head = item;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.next = ref.next;
|
||||||
|
item.prev = ref;
|
||||||
|
ref.next = item;
|
||||||
|
if (ref === this.tail)
|
||||||
|
this.tail = item;
|
||||||
|
};
|
||||||
|
|
||||||
|
LRU.prototype._remove = function insert(item) {
|
||||||
|
if (item.prev)
|
||||||
|
item.prev.next = item.next;
|
||||||
|
|
||||||
|
if (item.next)
|
||||||
|
item.next.prev = item.prev;
|
||||||
|
|
||||||
|
if (this.head === item)
|
||||||
|
this.head = item.next;
|
||||||
|
|
||||||
|
if (this.tail === item)
|
||||||
|
this.tail = item.prev;
|
||||||
|
|
||||||
|
item.prev = null;
|
||||||
|
item.next = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
LRU.prototype._keys = function _keys() {
|
||||||
|
var keys = [];
|
||||||
|
var item;
|
||||||
|
for (item = this.head; item; item = item.next) {
|
||||||
|
if (item === this.head)
|
||||||
|
assert(!item.prev);
|
||||||
|
if (!item.prev)
|
||||||
|
assert(item === this.head);
|
||||||
|
if (!item.next)
|
||||||
|
assert(item === this.tail);
|
||||||
|
keys.push(item.key);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
var a1 = '1';
|
||||||
|
var a2 = '2';
|
||||||
|
var a3 = '3';
|
||||||
|
var a4 = '4';
|
||||||
|
var a5 = '5';
|
||||||
|
var lru = new LRU(5);
|
||||||
|
lru.set('a1', a1);
|
||||||
|
assert(lru.get('a1') === '1');
|
||||||
|
assert(lru.size === 1);
|
||||||
|
assert(lru.head.key === 'a1' && lru.tail.key === 'a1' && !lru.head.prev && !lru.head.next);
|
||||||
|
console.log(lru._keys());
|
||||||
|
lru.set('a2', a2);
|
||||||
|
assert(lru.get('a2') === '2');
|
||||||
|
assert(lru.size === 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.set('a3', a3);
|
||||||
|
assert(lru.get('a3') === '3');
|
||||||
|
assert(lru.size === 3);
|
||||||
|
console.log(lru._keys());
|
||||||
|
lru.set('a3', a3);
|
||||||
|
assert(lru.get('a3') === '3');
|
||||||
|
assert(lru.size === 3);
|
||||||
|
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.get('a1'));
|
||||||
|
lru.remove('a1');
|
||||||
|
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');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user