Skip to content

Instantly share code, notes, and snippets.

@cometkim
Last active December 23, 2024 17:19
Show Gist options
  • Save cometkim/31a54fe69efeb367d163c5b58f475baf to your computer and use it in GitHub Desktop.
Save cometkim/31a54fe69efeb367d163c5b58f475baf to your computer and use it in GitHub Desktop.
There are too many LRU implementations in JS...

JavaScript LRU library benchmark

There are too many LRU(Least Recently Used) implementations in JS.

I recommend to use flru which is the smallest one and fast enough. Unless you need more rich functionality.

However, it's performance is vary depend on the host environment. For example, flru loses on Bun.

If you need micro-optimization on it, measure it yourself in your environment.

Acknowledgement

This benchmark is ported from @lukeed's flru benchmark suite.

import { barplot, run, bench } from 'mitata';
import { LRUCache } from 'lru-cache';
import TmpCache from 'tmp-cache';
import { lru as TinyLRU } from 'tiny-lru';
import PicoLRU from 'picolru';
import QuickLRU from 'quick-lru';
import { createLRU } from 'lru.min';
import fLRU from 'flru';
// Packages doesn't natively support ESM
import LRUMapPkg from 'lru_map';
const LRUMap = LRUMapPkg.LRUMap;
const limit = 2000;
const libs = {
'lru-cache': new LRUCache({ max: limit }),
'tmp-cache': new TmpCache(limit),
'tiny-lru': TinyLRU(limit),
'picolru': new PicoLRU({ maxSize: limit }),
'quick-lru': new QuickLRU({ maxSize: limit }),
'lru_map': new LRUMap(limit),
'lru.min': createLRU({ max: limit }),
'flru': fLRU(limit),
};
// with random string keys
const random = () => Math.random().toString(36).substring(4);
const full = Array.from({ length: limit * 2 }, random);
const samples = full.slice(limit);
// set
barplot(() => {
for (const [libName, impl] of Object.entries(libs)) {
bench(libName, () => {
samples.forEach((k, i) => void impl.set(k, i));
});
}
});
// has
barplot(() => {
for (const [libName, impl] of Object.entries(libs)) {
bench(libName, () => {
samples.forEach(k => void impl.has(k));
});
}
});
// get
barplot(() => {
for (const [libName, impl] of Object.entries(libs)) {
bench(libName, () => {
samples.forEach(k => void impl.get(k));
});
}
});
// update
barplot(() => {
for (const [libName, impl] of Object.entries(libs)) {
bench(libName, () => {
samples.forEach(k => void impl.set(k, k.length));
});
}
});
// evict
barplot(() => {
for (const [libName, impl] of Object.entries(libs)) {
bench(libName, () => {
full.forEach((k, i) => void impl.set(k, i));
});
}
});
await run();
{
"devDependencies": {
"flru": "1.0.2",
"lru_map": "0.4.1",
"lru-cache": "11.0.2",
"lru.min": "1.1.1",
"mitata": "1.0.11",
"picolru": "1.2.0",
"quick-lru": "7.0.0",
"tiny-lru": "11.2.11",
"tmp-cache": "1.1.0"
}
}
clk: ~3.02 GHz
cpu: Apple M1 Pro
runtime: node 22.9.0 (arm64-darwin)
benchmark avg (min … max) p75 p99 (min … top 1%)
-------------------------------------- -------------------------------
set
-------------------------------------- -------------------------------
lru-cache 64.84 µs/iter 70.67 µs █▇
(58.71 µs … 322.42 µs) 87.25 µs ██▃▂▂▂▂▂▇▇▂▂▂▂▂▁▁▁▁▁▁
tmp-cache 182.71 µs/iter 151.88 µs █
(111.79 µs … 5.06 ms) 1.24 ms ▄█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
tiny-lru 44.55 µs/iter 42.71 µs █
(40.42 µs … 179.21 µs) 74.00 µs █▂▂▁▁▁▄▁▁▁▁▁▁▁▁▁▁▁▂▁▁
picolru 68.84 µs/iter 71.25 µs █
(62.38 µs … 502.63 µs) 99.58 µs ██▂▁▁▇▂▁▁▁▁▁▁▁▁▁▁▁▄▁▁
quick-lru 113.24 µs/iter 116.17 µs ▃ █
(93.83 µs … 1.30 ms) 287.96 µs █▇█▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
lru_map 68.55 µs/iter 67.79 µs ▄▃█
(63.29 µs … 164.25 µs) 95.71 µs ███▆▃▁▁▁▁▁▁▁▁▁▁▁▂▃▂▁▁
lru.min 59.76 µs/iter 60.71 µs ▇▅▆█
(56.58 µs … 120.83 µs) 71.63 µs ▄██████▇▄▂▁▁▁▁▁▁▁▁▁▁▁
flru 40.05 µs/iter 40.29 µs █
(38.33 µs … 91.29 µs) 43.88 µs ▃▇▆▇▄▆█▆▃▂▃▃▃▃▂▁▁▁▁▁▁
┌ ┐
lru-cache ┤■■■■■■ 64.84 µs
tmp-cache ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 182.71 µs
tiny-lru ┤■■ 44.55 µs
picolru ┤■■■■■■■ 68.84 µs
quick-lru ┤■■■■■■■■■■■■■■■■■■ 113.24 µs
lru_map ┤■■■■■■■ 68.55 µs
lru.min ┤■■■■■ 59.76 µs
flru ┤■ 40.05 µs
└ ┘
has
-------------------------------------- -------------------------------
lru-cache 34.66 µs/iter 35.54 µs ▇█▅▄
(28.71 µs … 122.42 µs) 53.63 µs ████▃▇▄▂▂▁▁▁▁▁▁▃▅▅▃▁▁
tmp-cache 4.36 µs/iter 4.43 µs █▃ ▃ █ █▃▃█ ▃
(4.23 µs … 4.50 µs) 4.47 µs ██▆▆▆▁▆▁█▆▆▆█▁████▁█▁
tiny-lru 20.62 µs/iter 19.94 µs █ █
(19.82 µs … 28.32 µs) 20.25 µs ████████▁▁▁▁▁▁▁▁▁▁▁▁▁
picolru 773.19 ns/iter 667.00 ns ▄█
(542.00 ns … 58.63 µs) 4.25 µs ██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
quick-lru 72.59 µs/iter 78.54 µs █
(67.92 µs … 124.63 µs) 84.25 µs ▃█▇▁▂▂▁▁▁▁▁▁▂▇▅▁▁▁▁▁▁
lru_map 48.32 µs/iter 48.29 µs ▄ █
(47.17 µs … 116.83 µs) 53.42 µs ▁█▇██▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁
lru.min 44.34 µs/iter 44.25 µs █▅
(43.38 µs … 106.63 µs) 49.17 µs ▁▄██▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
flru 29.35 µs/iter 29.34 µs █ █
(29.06 µs … 30.44 µs) 29.53 µs ██▁▁██▁█▁█▁▁█▁▁▁▁█▁▁▁
┌ ┐
lru-cache ┤■■■■■■■■■■■■■■■■■ 34.66 µs
tmp-cache ┤■■ 4.36 µs
tiny-lru ┤■■■■■■■■■■ 20.62 µs
picolru ┤■ 773.19 ns
quick-lru ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 72.59 µs
lru_map ┤■■■■■■■■■■■■■■■■■■■■■■■ 48.32 µs
lru.min ┤■■■■■■■■■■■■■■■■■■■■■ 44.34 µs
flru ┤■■■■■■■■■■■■■■ 29.35 µs
└ ┘
get
-------------------------------------- -------------------------------
lru-cache 40.65 µs/iter 40.58 µs █ ▇
(34.46 µs … 103.71 µs) 57.79 µs █▆▇▃▁█▂▁▁▁▁▁▁▁▁▁█▂▂▂▁
tmp-cache 180.42 µs/iter 158.75 µs █
(122.83 µs … 4.20 ms) 295.63 µs ▂▁▂█▇▅▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁
tiny-lru 62.51 µs/iter 65.71 µs █
(57.33 µs … 151.17 µs) 89.33 µs █▇▂▂▁▅▃▁▁▁▁▁▁▁▁▁▁▁▃▁▁
picolru 91.09 µs/iter 92.71 µs █
(80.29 µs … 173.38 µs) 134.00 µs █▅▂▁▃▇▂▁▁▁▁▁▁▁▁▁▁▁▄▁▁
quick-lru 186.30 µs/iter 187.88 µs █
(171.17 µs … 452.71 µs) 277.37 µs ▃▂██▄▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
lru_map 67.28 µs/iter 65.13 µs █
(63.50 µs … 147.08 µs) 92.29 µs ▄█▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▁▁
lru.min 56.30 µs/iter 56.21 µs █▄
(55.00 µs … 100.21 µs) 62.50 µs ▁███▄▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁
flru 28.98 µs/iter 28.99 µs █
(28.70 µs … 30.33 µs) 29.25 µs ▄▇█▁▁▁▁▁▁▁▄▁▁▁▁▁▁▁▁▁▄
┌ ┐
lru-cache ┤■■■ 40.65 µs
tmp-cache ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 180.42 µs
tiny-lru ┤■■■■■■■■ 62.51 µs
picolru ┤■■■■■■■■■■■■■■ 91.09 µs
quick-lru ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 186.30 µs
lru_map ┤■■■■■■■■■ 67.28 µs
lru.min ┤■■■■■■ 56.30 µs
flru ┤■ 28.98 µs
└ ┘
update
-------------------------------------- -------------------------------
lru-cache 64.62 µs/iter 70.25 µs █
(55.58 µs … 1.15 ms) 142.50 µs █▆▃▇▄▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
tmp-cache 175.33 µs/iter 149.04 µs █▃
(108.46 µs … 4.28 ms) 413.04 µs ▁▃██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
tiny-lru 47.76 µs/iter 47.67 µs ▅█▃
(42.29 µs … 133.63 µs) 78.88 µs ███▂▁█▂▂▁▁▁▁▁▁▁▁▁▂▂▂▂
picolru 71.39 µs/iter 75.63 µs ██
(63.13 µs … 151.21 µs) 103.29 µs ██▆▃▁▃▆▅▄▁▁▁▁▁▁▁▁▂▃▂▁
quick-lru 116.00 µs/iter 117.88 µs ▃█
(95.79 µs … 1.26 ms) 309.63 µs ███▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
lru_map 69.94 µs/iter 69.25 µs █▆█
(64.96 µs … 135.00 µs) 96.75 µs ███▇▄▁▁▁▁▁▁▁▁▁▁▁▃▁▃▂▁
lru.min 61.30 µs/iter 60.88 µs █▅
(59.71 µs … 179.63 µs) 69.63 µs ▁██▃▁▂▂▂▁▂▂▁▁▁▁▁▁▁▁▁▁
flru 41.04 µs/iter 41.20 µs █
(40.60 µs … 42.11 µs) 41.33 µs █▁▁███▁█▁▁▁█▁▁▁█▁█▁█▁
┌ ┐
lru-cache ┤■■■■■■ 64.62 µs
tmp-cache ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 175.33 µs
tiny-lru ┤■■ 47.76 µs
picolru ┤■■■■■■■■ 71.39 µs
quick-lru ┤■■■■■■■■■■■■■■■■■■■ 116.00 µs
lru_map ┤■■■■■■■■ 69.94 µs
lru.min ┤■■■■■■ 61.30 µs
flru ┤■ 41.04 µs
└ ┘
evict
-------------------------------------- -------------------------------
lru-cache 421.60 µs/iter 421.17 µs ▇█
(383.50 µs … 1.44 ms) 713.83 µs ▂██▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
tmp-cache 3.53 ms/iter 3.58 ms █ ▇▂▅▅▂▅▅▆▃▅▂▄▅▅
(3.37 ms … 6.77 ms) 3.70 ms ▄█▇██████████████▅▁▂▁
tiny-lru 358.04 µs/iter 361.08 µs ▇█
(283.58 µs … 1.87 ms) 638.79 µs ▂▅▇██▇▄▂▂▂▁▁▁▁▁▁▁▁▁▁▁
picolru 426.44 µs/iter 423.46 µs █
(394.00 µs … 1.86 ms) 621.75 µs ▂▄█▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
quick-lru 226.03 µs/iter 229.96 µs ▅▃█▇
(193.50 µs … 1.54 ms) 441.58 µs ████▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
lru_map 451.55 µs/iter 393.08 µs █
(355.54 µs … 3.67 ms) 2.86 ms █▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
lru.min 392.19 µs/iter 378.88 µs █▂
(348.17 µs … 5.73 ms) 475.21 µs ▂▃▅██▅▃▂▂▂▁▁▁▂▁▁▁▁▁▁▁
flru 157.47 µs/iter 156.08 µs █▄
(146.96 µs … 431.25 µs) 291.92 µs ██▅▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
┌ ┐
lru-cache ┤■■■ 421.60 µs
tmp-cache ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 3.53 ms
tiny-lru ┤■■■ 358.04 µs
picolru ┤■■■ 426.44 µs
quick-lru ┤■ 226.03 µs
lru_map ┤■■■ 451.55 µs
lru.min ┤■■■ 392.19 µs
flru ┤■ 157.47 µs
└ ┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment