Skip to content

Instantly share code, notes, and snippets.

@db
Last active September 25, 2015 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save db/995108 to your computer and use it in GitHub Desktop.
Save db/995108 to your computer and use it in GitHub Desktop.
LRU cache
var Cache = function(pMaxSize) {
this.lastID = 0;
this.items = {};
this.numItems = 0;
var maxSize = parseInt(pMaxSize, 10);
if (isNaN(maxSize)) maxSize = -1;
this.maxNumItems = maxSize;
this.itemDefault = {
ttl : 3600, // time to live = 1 hour
priority : 2 // 1=low, 2=medium, 3=high
};
};
Cache.prototype = {
add : function(pKey, pValue, pTtl, pPriority) {
if (!pKey || !pValue) return false;
var ttl = pTtl || this.itemDefault.ttl, priority = pPriority || this.itemDefault.priority;
if (this.items[pKey] !== null) {
this.lastID++;
this.del(pKey);
this.items[pKey] = {
id : this.lastID,
key : pKey,
value : pValue,
ttl : ttl * 1000,
priority : priority,
accessed : new Date().getTime()
};
}
if (this.maxNumItems > 0 && this.numItems >= this.maxNumItems) this.purge();
this.numItems += 1;
return this.items[pKey];
},
get : function(pKey) {
var item = this.items[pKey];
var get = null;
if (item) {
if (!this.isExpired(item)) {
item.accessed = new Date().getTime();
get = item.value;
}
else {
this.del(pKey);
}
}
return get;
},
del : function(pKey) {
if (!pKey) return false;
if (this.items[pKey]) {
delete this.items[pKey];
this.numItems -= 1;
return true;
}
return false;
},
clear : function() {
for ( var key in this.items) this.del(key);
return true;
},
purge : function() {
var cacheSize = this.numItems, itemsToKeep = [], item, lastItem;
for ( var key in this.items) {
item = this.items[key];
if (this.isExpired(item)) {
this.del(key);
}
else {
itemsToKeep.push(item);
}
}
if (itemsToKeep.length > this.maxNumItems) {
// sort by priority and last accessed time
itemsToKeep = itemsToKeep.sort(function(pItemA, pItemB) {
// lower priority expires first
if (pItemA.priority != pItemB.priority) {
return pItemB.priority - pItemA.priority;
}
// least recently accessed is less important,
// it expires first
if (pItemA.accessed != pItemB.accessed) {
return pItemB.accessed - pItemA.accessed;
}
// earliest created expires first
return pItemB.id - pItemA.id;
});
// remove excess
while (itemsToKeep.length > this.maxNumItems) {
lastItem = itemsToKeep.pop();
this.del(lastItem.key);
}
}
return (this.numItems - cacheSize);
},
isExpired : function(pItem) {
var now = new Date().getTime();
return (pItem.ttl < (now - pItem.accessed));
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment