Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: isaacs/node-lru-cache
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v7.0.1
Choose a base ref
...
head repository: isaacs/node-lru-cache
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v7.0.2
Choose a head ref
  • 6 commits
  • 7 files changed
  • 2 contributors

Commits on Feb 8, 2022

  1. chore: add copyright year to license

    License Year Bot committed Feb 8, 2022

    Verified

    This commit was signed with the committer’s verified signature.
    targos Michaël Zasso
    Copy the full SHA
    1d3761e View commit details
  2. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    MylesBorins Myles Borins
    Copy the full SHA
    caf43e1 View commit details
  3. 7.0.1

    isaacs committed Feb 8, 2022

    Verified

    This commit was signed with the committer’s verified signature.
    BethGriggs Bethany Griggs
    Copy the full SHA
    51cda55 View commit details

Commits on Feb 9, 2022

  1. Verified

    This commit was signed with the committer’s verified signature.
    BethGriggs Bethany Griggs
    Copy the full SHA
    faf81e2 View commit details
  2. add publishConfig tag

    isaacs committed Feb 9, 2022

    Verified

    This commit was signed with the committer’s verified signature.
    BethGriggs Bethany Griggs
    Copy the full SHA
    950e485 View commit details
  3. 7.0.2

    isaacs committed Feb 9, 2022

    Verified

    This commit was signed with the committer’s verified signature.
    BethGriggs Bethany Griggs
    Copy the full SHA
    02c726f View commit details
Showing with 85 additions and 16 deletions.
  1. +1 −1 LICENSE
  2. +11 −11 README.md
  3. +3 −1 index.js
  4. +2 −2 package-lock.json
  5. +4 −1 package.json
  6. +11 −0 test/basic.js
  7. +53 −0 test/load-check.js
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The ISC License

Copyright (c) Isaac Z. Schlueter and Contributors
Copyright (c) 2010-2022 Isaac Z. Schlueter and Contributors

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -341,12 +341,12 @@ ignored.
As of January 2022, version 7 of this library is one of the most performant
LRU cache implementations in JavaScript.

Note that benchmarks can be extremely difficult to get right. In
particular, the performance of set/get/delete operations on objects will
vary _wildly_ depending on the type of key used. V8 is highly optimized
for objects with keys that are short strings, especially integer numeric
strings. Thus any benchmark which tests _solely_ using numbers as keys
will tend to find that an object-based approach performs the best.
Benchmarks can be extremely difficult to get right. In particular, the
performance of set/get/delete operations on objects will vary _wildly_
depending on the type of key used. V8 is highly optimized for objects with
keys that are short strings, especially integer numeric strings. Thus any
benchmark which tests _solely_ using numbers as keys will tend to find that
an object-based approach performs the best.

Note that coercing _anything_ to strings to use as object keys is unsafe,
unless you can be 100% certain that no other type of value will be used.
@@ -383,12 +383,13 @@ If performance matters to you:

1. If it's at all possible to use small integer values as keys, and you can
guarantee that no other types of values will be used as keys, then do that,
and use `mode: 'object'`.
and use a cache such as [lru-fast](https://npmjs.com/package/lru-fast)
which uses an Object as its data store.
2. Failing that, if at all possible, use short non-numeric strings (ie,
less than 256 characters) as your keys, with `mode: 'object'`.
less than 256 characters) as your keys.
3. If you know that the types of your keys will be long strings, strings
that look like floats, `null`, objects, or some mix of any random thing,
then use `mode: 'map'` to skip the detection logic.
that look like floats, `null`, objects, or some mix of types, then this
library will work well for you.
4. Do not use a `dispose` function, size tracking, or ttl behavior, unless
absolutely needed. These features are convenient, and necessary in some
use cases, and every attempt has been made to make the performance
@@ -413,7 +414,6 @@ well.
* The `set()`, `get()`, and `has()` functions take options objects
instead of positional booleans/integers for optional parameters.
* `size` can be set explicitly on `set()`.
* `updateAgeOnHas` and `updateRecencyOnHas` added.
* `cache.length` was renamed to the more fitting `cache.size`.
* Option name deprecations:
* `stale` -> `allowStale`
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -117,6 +117,7 @@ class LRUCache {
this.head = 0
this.tail = 0
this.free = new Stack(max)
this.initialFill = 1
this.size = 0

if (typeof dispose === 'function') {
@@ -337,7 +338,7 @@ class LRUCache {
return this.free.pop()
}
// initial fill, just keep writing down the list
return this.tail + 1
return this.initialFill++
}

evict () {
@@ -448,6 +449,7 @@ class LRUCache {
}
this.head = 0
this.tail = 0
this.initialFill = 1
this.free.length = 0
this.calculatedSize = 0
this.size = 0
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
"version": "7.0.0",
"version": "7.0.2",
"publishConfig": {
"tag": "v7.0-backport"
},
"author": "Isaac Z. Schlueter <i@izs.me>",
"keywords": [
"mru",
11 changes: 11 additions & 0 deletions test/basic.js
Original file line number Diff line number Diff line change
@@ -126,3 +126,14 @@ t.test('peek does not disturb order', t => {
t.strictSame([...c.values()], [4, 3, 2, 1, 0])
t.end()
})

t.test('re-use key before initial fill completed', t => {
const c = new LRU({ max: 5 })
c.set(0, 0)
c.set(1, 1)
c.set(2, 2)
c.set(1, 2)
c.set(3, 3)
t.same([...c.entries()], [ [ 3, 3 ], [ 1, 2 ], [ 2, 2 ], [ 0, 0 ] ])
t.end()
})
53 changes: 53 additions & 0 deletions test/load-check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
process.env.TAP_BAIL = '1'
const t = require('tap')
const LRU = require('../')
const max = 10000
const cache = new LRU({ max })

const crypto = require('crypto')
const getVal = () => [
crypto.randomBytes(12).toString('hex'),
crypto.randomBytes(12).toString('hex'),
crypto.randomBytes(12).toString('hex'),
crypto.randomBytes(12).toString('hex'),
]

const seeds = new Array(max * 3)
// fill up the cache to start
for (let i = 0; i < max * 3; i++) {
const v = getVal()
seeds[i] = [v.join(':'), v]
}
t.pass('generated seed data')

const verifyCache = () => {
// walk down the internal list ensuring that every key is the key to that
// index in the keyMap, and the value matches.
for (const [k, i] of (cache.map || cache.keyMap).entries()) {
const v = cache.valList[i]
const key = cache.keyList[i]
if (k !== key) {
t.equal(k, key, 'key at proper index', { k, i })
}
if (v.join(':') !== k) {
t.equal(k, v.join(':'), 'proper value at index', { v, i })
}
}
}

let cycles = 0
const cycleLength = Math.floor(max / 100)
while (cycles < max * 5) {
const r = Math.floor(Math.random() * seeds.length)
const seed = seeds[r]
const v = cache.get(seed[0])
if (v === undefined) {
cache.set(seed[0], seed[1])
} else {
t.equal(v.join(':'), seed[0], 'correct get ' + cycles, { seed, v })
}
if (++cycles % cycleLength === 0) {
verifyCache()
t.pass('cycle check ' + cycles)
}
}