Least Recently Used (LRU) cache algorithm
This is an older version aimed for older JS environments lacking some post-ES5 features like Map and Symbol. If you're targeting a modern web browser or Nodejs, consider using the latest version instead.
A finite key-value cache using the Least Recently Used (LRU) cache algorithm where the most recently used objects are keept in cache while less recently used items are purged.
This implementation is compatible with most JavaScript environments (including ye olde browser) and is very efficient.
Terminology & design
-
Based on a doubly-linked list for low complexity random shuffling of entries.
-
The cache object iself has a "head" (least recently used entry) and a "tail" (most recently used entry).
-
The "head" and "tail" are "entries" -- an entry might have a "newer" and an "older" entry (doubly-linked, "older" being close to "head" and "newer" being closer to "tail").
-
Key lookup is done through a key-entry mapping native object, which on most platforms mean
O(1)
complexity. This comes at a very low memory cost (for storing two extra pointers for each entry).
Fancy ASCII art illustration of the general design:
entry entry entry entry ______ ______ ______ ______ | head |.newer => | |.newer => | |.newer => | tail | .oldest = | A | | B | | C | | D | = .newest |______| <= older.|______| <= older.|______| <= older.|______| removed <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- added
Example
let c = 3cccc // -> "adam:29 < john:26 < angela:24"c // -> 26 // Now 'john' is the most recently used entry, since we just requested itc // -> "adam:29 < angela:24 < john:26"c // -> {key:adam, value:29} // Because we only have room for 3 entries, put-ing 'zorro' purged 'adam'c // -> "angela:24 < john:26 < zorro:141"
Usage
Just copy the code on lru.js — for minimal functionality, you only need the lines up until the comment that says "Following code is optional".
If you're really into package managers and love having lots of complicated little files in your project, you can use npm install lru-fast
Additionally:
- Run tests with
npm test
- Run benchmarks with
npm run benchmark
API
// An entry holds the key and value, and pointers to any older and newer entries.
If you need to perform any form of finalization of items as they are evicted from the cache, wrapping the shift
method is a good way to do it:
let c = 123;c { let entry = LRUCacheprototypeshift; ; return entry;}
The internals calls shift
as entries need to be evicted, so this method is guaranteed to be called for any item that's removed from the cache. The returned entry must not include any strong references to other entries. See note in the documentation of LRUCache.prototype.put (Object key, Object value) -> Object entry
.
MIT license
Copyright (c) 2010-2016 Rasmus Andersson https://rsms.me/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.