Permalink
Browse files

lru-cache@2.0.4

  • Loading branch information...
1 parent b185df1 commit d8fb1ea87ed89d1903cbe7074f8ed3bf25723451 @isaacs isaacs committed Sep 25, 2012
Showing with 52 additions and 37 deletions.
  1. +31 −35 node_modules/lru-cache/lib/lru-cache.js
  2. +2 −2 node_modules/lru-cache/package.json
  3. +19 −0 node_modules/lru-cache/test/basic.js
@@ -1,6 +1,6 @@
;(function () { // closure for web browsers
-if (module) {
+if (typeof module === 'object' && module.exports) {
module.exports = LRUCache
} else {
// just set the global for non-node platforms.
@@ -21,7 +21,7 @@ function LRUCache (options) {
var max
if (typeof options === 'number') {
max = options
- options = {max: max}
+ options = { max: max }
}
max = options.max
@@ -33,16 +33,16 @@ function LRUCache (options) {
lengthCalculator = naiveLength
}
if (!max || !(typeof max === "number") || max <= 0 ) {
+ // a little bit silly. maybe this should throw?
max = Infinity
}
var maxAge = options.maxAge || null
var dispose = options.dispose
- var cache = {} // hash of items by key
- , lruList = {} // list of items in order of use recency
- , lru = 0 // least recently used
+ var cache = Object.create(null) // hash of items by key
+ , lruList = Object.create(null) // list of items in order of use recency
, mru = 0 // most recently used
, length = 0 // number of items in the list
, itemCount = 0
@@ -67,16 +67,16 @@ function LRUCache (options) {
if (typeof lC !== "function") {
lengthCalculator = naiveLength
length = itemCount
- Object.keys(cache).forEach(function (key) {
+ for (var key in cache) {
cache[key].length = 1
- })
+ }
} else {
lengthCalculator = lC
length = 0
- Object.keys(cache).forEach(function (key) {
+ for (var key in cache) {
cache[key].length = lengthCalculator(cache[key].value)
length += cache[key].length
- })
+ }
}
if (length > max) trim()
@@ -98,13 +98,12 @@ function LRUCache (options) {
this.reset = function () {
if (dispose) {
- Object.keys(cache).forEach(function (k) {
+ for (var k in cache) {
dispose(k, cache[k].value)
- })
+ }
}
cache = {}
lruList = {}
- lru = 0
mru = 0
length = 0
itemCount = 0
@@ -126,16 +125,15 @@ function LRUCache (options) {
return true
}
- var hit = {
- key:key,
- value:value,
- lu:mru++,
- length:lengthCalculator(value),
- now: (maxAge) ? Date.now() : 0
- }
+ var len = lengthCalculator(value)
+ var age = maxAge ? Date.now() : 0
+ var hit = new Entry(key, value, mru++, len, age)
// oversized objects fall out of cache automatically.
- if (hit.length > max) return false
+ if (hit.length > max) {
+ if (dispose) dispose(key, value)
+ return false
+ }
length += hit.length
lruList[hit.lu] = cache[key] = hit
@@ -153,7 +151,6 @@ function LRUCache (options) {
return
}
delete lruList[hit.lu]
- if (hit.lu === lru) lruWalk()
hit.lu = mru ++
lruList[hit.lu] = hit
return hit.value
@@ -165,31 +162,30 @@ function LRUCache (options) {
if (dispose) dispose(key, hit.value)
delete cache[key]
delete lruList[hit.lu]
- if (hit.lu === lru) lruWalk()
length -= hit.length
itemCount --
}
- function lruWalk () {
- // lru has been deleted, hop up to the next hit.
- for (var key in lruList) {
- return key
- }
- }
-
function trim () {
if (length <= max) return
- var prune = Object.keys(lruList)
- for (var i = 0; i < prune.length && length > max; i ++) {
- var hit = lruList[prune[i]]
+ for (var k in lruList) {
+ if (length <= max) break;
+ var hit = lruList[k]
if (dispose) dispose(hit.key, hit.value)
length -= hit.length
delete cache[ hit.key ]
- delete lruList[prune[i]]
+ delete lruList[k]
}
-
- lruWalk()
}
}
+// classy, since V8 prefers predictable objects.
+function Entry (key, value, mru, len, age) {
+ this.key = key
+ this.value = value
+ this.lu = mru
+ this.length = len
+ this.now = age
+}
+
})()
@@ -1,7 +1,7 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
- "version": "2.0.2",
+ "version": "2.0.4",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me"
@@ -52,6 +52,6 @@
}
],
"readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum number of items. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n",
- "_id": "lru-cache@2.0.2",
+ "_id": "lru-cache@2.0.4",
"_from": "lru-cache@~2.0.0"
}
@@ -246,3 +246,22 @@ test("disposal function", function(t) {
t.equal(disposed, 3)
t.end()
})
+
+test("disposal function on too big of item", function(t) {
+ var disposed = false
+ var cache = new LRU({
+ max: 1,
+ length: function (k) {
+ return k.length
+ },
+ dispose: function (k, n) {
+ disposed = n
+ }
+ })
+ var obj = [ 1, 2 ]
+
+ t.equal(disposed, false)
+ cache.set("obj", obj)
+ t.equal(disposed, obj)
+ t.end()
+})

0 comments on commit d8fb1ea

Please sign in to comment.