\n\nTiny & Fast LRU Implementation as possible.
\n
There are a lot of LRU implementations, but most of them have a poor perfomance and they are hard to understand.
\nhyperlru is an Abstract LRU implementation using traditional and efficienty data structures:
\nFor use it, you need to provide one of the created providers:
\n\n$ npm install hyperlru --save
const hyperlru = require('hyperlru')\nconst myProvider = require('my-hyperlru-provider')\n\nconst createLRU = hyperlru(myProvider)\nconst cache = createLRU({max: 1000})
name | \nsize | \ngzip | \nset | \nget1 | \nupdate | \nget2 | \nevict | \n
---|---|---|---|---|---|---|---|
lru-fast | \n2.34 kB | \n793 B | \n6855 | \n27105 | \n21550 | \n25159 | \n4003 | \n
tiny-lru | \n4 kB | \n1.64 kB | \n4159 | \n10746 | \n18909 | \n15925 | \n4042 | \n
lru_cache | \n2.19 kB | \n756 B | \n5320 | \n14489 | \n10785 | \n15963 | \n4242 | \n
simple-lru-cache | \n1.43 kB | \n565 B | \n3289 | \n12134 | \n8600 | \n15266 | \n3334 | \n
hyperlru-object | \n433 B | \n265 B | \n1152 | \n8800 | \n6205 | \n8635 | \n1039 | \n
hashlru | \n628 B | \n332 B | \n4438 | \n5834 | \n4703 | \n5960 | \n3474 | \n
hyperlru-map | \n329 B | \n232 B | \n850 | \n4555 | \n4030 | \n4397 | \n690 | \n
lru | \n6.07 kB | \n1.86 kB | \n2672 | \n3302 | \n3142 | \n3898 | \n1347 | \n
lru-cache | \n19.1 kB | \n6.23 kB | \n989 | \n4702 | \n3034 | \n4536 | \n773 | \n
secondary-cache | \n22.6 kB | \n6.54 kB | \n1427 | \n2292 | \n2740 | \n4579 | \n1164 | \n
quick-lru | \n1.23 kB | \n489 B | \n2441 | \n2075 | \n2525 | \n2119 | \n2525 | \n
modern-lru | \n2.27 kB | \n907 B | \n1019 | \n2531 | \n2021 | \n2456 | \n731 | \n
mkc | \n10.5 kB | \n3.61 kB | \n729 | \n1230 | \n715 | \n1129 | \n575 | \n
Type: number
\nDefault: 1000
Max of element to keep into the cache.
\nSet the value of the key and mark the key as most recently used.
\nIt returns the value
.
Query the value of the key and mark the key as most recently used.
\nIt returns the value of key if found; undefined
otherwise.
Query the value of the key without marking the key as most recently used.
\nIt returns the value of key if found; undefined
otherwise.
It retrieves all the keys currently in the cache.
\nIt retrieves all the values currently in the cache.
\nClear all the elements in the cache.
\nRemove the value from the cache.
\nReturns: value of key if found; undefined
otherwise.
MIT © Kiko Beats.
\n" 79 | }, 80 | { 81 | "component": "footer", 82 | "links": [ 83 | { 84 | "href": "https://github.com/Kikobeats/hyperlru", 85 | "text": "GitHub" 86 | }, 87 | { 88 | "href": "https://github.com/Kikobeats", 89 | "text": "Kikobeats" 90 | } 91 | ] 92 | } 93 | ] 94 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = require('./src') 4 | module.exports.test = require('./test') 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperlru", 3 | "description": "Tiny & Fast LRU Implementation as possible", 4 | "homepage": "https://github.com/Kikobeats/hyperlru", 5 | "version": "2.1.2", 6 | "main": "index.js", 7 | "author": { 8 | "email": "josefrancisco.verdu@gmail.com", 9 | "name": "Kiko Beats", 10 | "url": "https://github.com/Kikobeats" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/kikobeats/hyperlru.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/Kikobeats/hyperlru/issues" 18 | }, 19 | "keywords": [ 20 | "buffer", 21 | "cache", 22 | "caching", 23 | "fast", 24 | "hash", 25 | "least", 26 | "lru", 27 | "mru", 28 | "quick", 29 | "recently", 30 | "used" 31 | ], 32 | "dependencies": { 33 | "linked-list": "~2.1.0" 34 | }, 35 | "devDependencies": { 36 | "git-dirty": "latest", 37 | "should": "latest", 38 | "standard": "latest", 39 | "standard-markdown": "latest" 40 | }, 41 | "engines": { 42 | "node": ">= 6" 43 | }, 44 | "files": [ 45 | "index.js", 46 | "src/index.js", 47 | "test/index.js" 48 | ], 49 | "scripts": { 50 | "clean": "rm -rf node_modules", 51 | "lint": "standard-markdown && standard", 52 | "pretest": "npm run lint", 53 | "test": "echo 'test on connectors'" 54 | }, 55 | "license": "MIT", 56 | "standard": { 57 | "globals": [ 58 | "describe", 59 | "it" 60 | ] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const LinkedList = require('linked-list') 4 | const exists = value => value !== undefined 5 | 6 | const hyperlru = createStore => { 7 | if (!createStore) { 8 | return new TypeError('You need to specify an store implementation') 9 | } 10 | 11 | return ({ max }) => { 12 | let dict = createStore() 13 | let list = new LinkedList() 14 | let size = max 15 | 16 | const _get = ({ isPeek }) => key => { 17 | const entry = dict.get(key) 18 | if (!exists(entry)) return 19 | if (isPeek) list.append(entry) 20 | return entry.value 21 | } 22 | 23 | function set (key, value) { 24 | let entry = dict.get(key) 25 | 26 | if (exists(entry)) { 27 | entry.value = value 28 | list.append(entry) 29 | } else { 30 | entry = Object.assign(new LinkedList.Item(), { key, value }) 31 | dict.set(key, entry) 32 | !size ? dict.delete(list.head.detach().key) : --size 33 | list.append(entry) 34 | } 35 | 36 | return value 37 | } 38 | 39 | function clear () { 40 | dict = createStore() 41 | list = new LinkedList() 42 | size = 0 43 | } 44 | 45 | function remove (key) { 46 | const entry = dict.get(key) 47 | if (!exists(entry)) return 48 | dict.delete(entry.detach().key) 49 | --size 50 | } 51 | 52 | const keys = () => dict.keys() 53 | const has = key => dict.has(key) 54 | const get = _get({ isPeek: true }) 55 | const peek = _get({ isPeek: false }) 56 | const values = () => dict.values() 57 | 58 | return { set, keys, get, clear, remove, has, peek, values } 59 | } 60 | } 61 | 62 | module.exports = hyperlru 63 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const should = require('should') 4 | const range = n => [...Array(n).keys()] 5 | const hyperlru = require('..') 6 | 7 | module.exports = createStore => { 8 | const createLRU = hyperlru(createStore) 9 | 10 | describe('constructor', function () { 11 | describe('options', function () { 12 | it('max', function () { 13 | const cache = createLRU({ max: 3 }) 14 | range(10).forEach((n) => cache.set(`foo${n}`, `bar${n}`)) 15 | should(cache.keys()).be.eql(['foo7', 'foo8', 'foo9']) 16 | }) 17 | }) 18 | }) 19 | 20 | describe('.get', function () { 21 | it('not previous set value is undefined', function () { 22 | const cache = createLRU({ max: 3 }) 23 | should(cache.get('foo')).be.undefined() 24 | }) 25 | it('return previous declared value', function () { 26 | const cache = createLRU({ max: 3 }) 27 | range(10).forEach((n) => cache.set(`foo${n}`, `bar${n}`)) 28 | should(cache.get('foo8')).be.equal('bar8') 29 | }) 30 | }) 31 | 32 | describe('.set', function () { 33 | it('set a value and retrieve it', function () { 34 | const cache = createLRU({ max: 3 }) 35 | should(cache.set('foo', 'bar')).be.equal('bar') 36 | }) 37 | }) 38 | 39 | describe('.keys', function () { 40 | it('retrieve all the keys', function () { 41 | const cache = createLRU({ max: 2 }) 42 | range(5).forEach((n) => cache.set(`foo${n}`, `bar${n}`)) 43 | should(cache.keys()).be.eql(['foo3', 'foo4']) 44 | }) 45 | }) 46 | 47 | describe('.clear', function () { 48 | it('remove all the elements', function () { 49 | const cache = createLRU({ max: 2 }) 50 | cache.set('foo', 'bar') 51 | cache.clear() 52 | should(cache.keys().length).be.equal(0) 53 | }) 54 | }) 55 | 56 | describe('.remove', function () { 57 | it('remove one time', function () { 58 | const cache = createLRU({ max: 2 }) 59 | range(5).forEach((n) => cache.set(`foo${n}`, `bar${n}`)) 60 | cache.remove('foo4') 61 | should(cache.keys()).be.eql(['foo3']) 62 | }) 63 | }) 64 | 65 | describe('.has', function () { 66 | it('a key that was added previously', function () { 67 | const cache = createLRU({ max: 2 }) 68 | cache.set('foo', 'bar') 69 | should(cache.has('foo')).be.true() 70 | }) 71 | }) 72 | 73 | describe('.values', function () { 74 | it('get all values present in the cache', function () { 75 | const cache = createLRU({ max: 2 }) 76 | cache.set('foo', 'bar') 77 | should(cache.values()).be.eql(['bar']) 78 | }) 79 | }) 80 | } 81 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require should 2 | --reporter spec 3 | --timeout 120000 4 | --slow 300 5 | --bail 6 | --recursive 7 | --------------------------------------------------------------------------------