Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More β†’
Socket
Sign inDemoInstall
Socket

lru.min

Package Overview
Dependencies
Maintainers
0
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lru.min - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

2

browser/lru.min.js

@@ -1,1 +0,1 @@

var createLRU=m=>{var x=m.max,f=null,i=null,y=0,t=0,v=new Map,d=m==null?void 0:m.dispose,K=m==null?void 0:m.maxAge,V=e=>{e.next=f,f&&(f.prev=e),f=e,i||(i=e),y++},g=e=>{e.prev&&(e.prev.next=e.next),e.next&&(e.next.prev=e.prev),e===f&&(f=e.next),e===i&&(i=e.prev),y--},A=e=>{g(e),V(e)};function n(e){var C,b;if(!(K||t))return!0;var a=Date.now();if(e){var r=v.get(e);if(!(r!=null&&r.timestamp))return!0;var u=(C=r.maxAge)!=null?C:K;return u&&a-r.timestamp>u?(s(r.key),!1):!0}for(var l=i;l!==null;l=l.prev)if(l!=null&&l.timestamp){var u=(b=l.maxAge)!=null?b:K;u&&a-l.timestamp>u&&s(l.key)}}var h=(e=1)=>{for(var a=0;a<e;a++){if(!i)return;var r=i.key,u=i.value;i.maxAge&&t>0&&t--,g(i),v.delete(r),d&&d(u,r)}},N=(e,a,r)=>{var u=v.get(e),l=K||r!=null&&r.maxAge?Date.now():void 0;if(r!=null&&r.maxAge&&!v.has(e)&&t++,u){u.value=a,u.timestamp=l,u.maxAge=r==null?void 0:r.maxAge,f!==u&&A(u);return}u={key:e,value:a,prev:null,next:null,timestamp:l},v.set(e,u),V(u),y>x&&h()},k=e=>{var a=v.get(e);if(a&&n(e))return f!==a&&A(a),a.value},p=e=>{var l;var a=v.get(e);if(a&&n(e)){if(a!=null&&a.timestamp){var r=Date.now(),u=(l=a.maxAge)!=null?l:K;if(u&&r-a.timestamp>u){s(e);return}}return a.value}},w=e=>n(e)?v.has(e):!1,z=()=>{for(var e=[],a=f;a!==null;a=a.next)n(a.key)&&e.push(a.key);return e},O=()=>{for(var e=[],a=f;a!==null;a=a.next)n(a.key)&&e.push(a.value);return e},D=()=>{for(var e=[],a=f;a!==null;a=a.next)n(a.key)&&e.push([a.key,a.value]);return e},L=e=>{for(var a=f;a!==null;a=a.next)n(a.key)&&e(a.value,a.key)},s=e=>{var a=v.get(e);return a?(a.maxAge&&t>0&&t--,g(a),v.delete(e),d&&d(a.value,e),!0):!1},R=()=>{if(d)for(var e of v.values())d(e.value,e.key);v.clear(),f=i=null,y=0,t=0},S=e=>{x=e;for(var a=y;a>x;a--)h()},U=()=>(n(),x-v.size),E=()=>(n(),v.size),H=()=>x;return{set:N,get:k,peek:p,has:w,keys:z,values:O,entries:D,forEach:L,del:s,evict:h,clear:R,resize:S,available:U,stored:E,maxSize:H}};
var createLRU=g=>{var{max:d,onEviction:t}=g;if(!(Number.isInteger(d)&&d>0))throw new TypeError("`max` must be a positive integer");var a=0,f=0,s=0,y=[],l=new Map,i=new Array(d).fill(void 0),n=new Array(d).fill(void 0),v=new Array(d).fill(0),m=new Array(d).fill(0),o=e=>{if(e!==s){var r=v[e];if(e===f)f=r;else{var u=m[e];v[u]=r,m[r]=u}v[s]=e,m[e]=s,s=e}},b=()=>{var e=f,r=i[e];return t==null||t(n[e],r),l.delete(r),i[e]=void 0,n[e]=void 0,f=v[e],a--,e};return{set(e,r){var u=l.get(e);u===void 0?(u=a===d?b():y.length>0?y.pop():a,l.set(e,u),i[u]=e,a++):t==null||t(n[u],e),n[u]=r,o(u)},get(e){var r=l.get(e);if(r!==void 0)return o(r),n[r]},peek:e=>{var r=l.get(e);return r!==void 0?n[r]:void 0},has:e=>l.has(e),*keys(){for(var e=f,r=0;r<a;r++)yield i[e],e=v[e]},*values(){for(var e=f,r=0;r<a;r++)yield n[e],e=v[e]},*entries(){for(var e=f,r=0;r<a;r++)yield[i[e],n[e]],e=v[e]},forEach:e=>{for(var r=f,u=0;u<a;u++){var K=i[r],h=n[r];e(h,K),r=v[r]}},delete(e){var r=l.get(e);return r!==void 0?(t==null||t(n[r],e),l.delete(e),y.push(r),i[r]=void 0,n[r]=void 0,a--,!0):!1},evict:e=>{for(var r=Math.min(e,a);r>0;)b(),r--},clear(){for(var e of l.values())t==null||t(n[e],i[e]);l.clear(),i.fill(void 0),n.fill(void 0),y=[],a=0,f=s=0},resize:e=>{if(!(Number.isInteger(e)&&e>0))throw new TypeError("`max` must be a positive integer");for(d=e;a>d;)b()},get max(){return d},get size(){return a},get available(){return d-a}}};

@@ -1,40 +0,37 @@

export interface LRUCacheOptions<Key extends string, Value> {
export declare const createLRU: <Key, Value>(options: {
/** Maximum number of items the cache can hold. */
max: number;
maxAge?: number;
dispose?: (value: Value, key: Key) => undefined;
}
export interface SetOptions {
maxAge?: number;
}
export declare const createLRU: <Key extends string, Value>(options: LRUCacheOptions<Key, Value>) => {
/** Function called when an item is evicted from the cache. */
onEviction?: (value: Value, key: Key) => unknown;
}) => {
/** Adds a key-value pair to the cache. Updates the value if the key already exists. */
set: (key: Key, value: Value, options?: SetOptions) => undefined;
set(key: Key, value: Value): undefined;
/** Retrieves the value for a given key and moves the key to the most recent position. */
get: (key: Key) => Value | undefined;
/** Retrieves the value for a given key without changing its position in the cache. */
get(key: Key): Value | undefined;
/** Retrieves the value for a given key without changing its position. */
peek: (key: Key) => Value | undefined;
/** Checks if a key exists in the cache. */
has: (key: Key) => boolean;
/** Returns an array of all keys in the cache, from most recent to least recent. */
keys: () => Key[];
/** Returns an array of all values in the cache, from most recent to least recent. */
values: () => Value[];
/** Returns an array of [key, value] pairs, from most recent to least recent. */
entries: () => [Key, Value][];
/** Iterates over all keys in the cache, from least recent to most recent. */
keys(): IterableIterator<Key>;
/** Iterates over all values in the cache, from least recent to most recent. */
values(): IterableIterator<Value>;
/** Iterates over `[key, value]` pairs in the cache, from least recent to most recent. */
entries(): IterableIterator<[Key, Value]>;
/** Iterates over each key-value pair in the cache, from most recent to least recent. */
forEach: (callback: (value: Value, key: Key) => undefined) => undefined;
forEach: (callback: (value: Value, key: Key) => unknown) => undefined;
/** Deletes a key-value pair from the cache. */
del: (key: Key) => boolean;
delete(key: Key): boolean;
/** Evicts the oldest item or the specified number of the oldest items from the cache. */
evict: (size?: number) => undefined;
evict: (number: number) => undefined;
/** Clears all key-value pairs from the cache. */
clear: () => undefined;
clear(): undefined;
/** Resizes the cache to a new maximum size, evicting items if necessary. */
resize: (newMax: number) => undefined;
/** Returns the number of available slots in the cache before reaching the maximum size. */
available: () => number;
/** Returns the maximum number of items that can be stored in the cache. */
readonly max: number;
/** Returns the number of items currently stored in the cache. */
stored: () => number;
/** Returns the maximum number of items that can be stored in the cache. */
maxSize: () => number;
readonly size: number;
/** Returns the number of currently available slots in the cache before reaching the maximum size. */
readonly available: number;
};
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var src_exports = {};
__export(src_exports, {
createLRU: () => createLRU
});
module.exports = __toCommonJS(src_exports);
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLRU = void 0;
const createLRU = (options) => {
let max = options.max;
let head = null;
let tail = null;
let size = 0;
let maxAgeCount = 0;
const map = /* @__PURE__ */ new Map();
const dispose = options == null ? void 0 : options.dispose;
const maxAge = options == null ? void 0 : options.maxAge;
const addNode = (node) => {
node.next = head;
if (head) head.prev = node;
head = node;
if (!tail) tail = node;
size++;
};
const removeNode = (node) => {
if (node.prev) node.prev.next = node.next;
if (node.next) node.next.prev = node.prev;
if (node === head) head = node.next;
if (node === tail) tail = node.prev;
size--;
};
const moveToHead = (node) => {
removeNode(node);
addNode(node);
};
function refresh(key) {
var _a, _b;
if (!(maxAge || maxAgeCount)) return true;
const now = Date.now();
if (key) {
const node = map.get(key);
if (!(node == null ? void 0 : node.timestamp)) return true;
const effectiveMaxAge = (_a = node.maxAge) != null ? _a : maxAge;
if (effectiveMaxAge && now - node.timestamp > effectiveMaxAge) {
del(node.key);
return false;
}
return true;
}
for (let current = tail; current !== null; current = current.prev) {
if (!(current == null ? void 0 : current.timestamp)) continue;
const effectiveMaxAge = (_b = current.maxAge) != null ? _b : maxAge;
if (effectiveMaxAge && now - current.timestamp > effectiveMaxAge)
del(current.key);
}
}
const evict = (size2 = 1) => {
for (let i = 0; i < size2; i++) {
if (!tail) return;
const tailKey = tail.key;
const tailValue = tail.value;
if (tail.maxAge && maxAgeCount > 0) {
maxAgeCount--;
}
removeNode(tail);
map.delete(tailKey);
if (dispose) dispose(tailValue, tailKey);
}
};
const set = (key, value, options2) => {
let node = map.get(key);
const now = maxAge || (options2 == null ? void 0 : options2.maxAge) ? Date.now() : void 0;
if ((options2 == null ? void 0 : options2.maxAge) && !map.has(key)) maxAgeCount++;
if (node) {
node.value = value;
node.timestamp = now;
node.maxAge = options2 == null ? void 0 : options2.maxAge;
if (head !== node) moveToHead(node);
return;
}
node = {
key,
value,
prev: null,
next: null,
timestamp: now
let { max, onEviction } = options;
if (!(Number.isInteger(max) && max > 0))
throw new TypeError('`max` must be a positive integer');
let size = 0;
let head = 0;
let tail = 0;
let free = [];
const keyMap = new Map();
const keyList = new Array(max).fill(undefined);
const valList = new Array(max).fill(undefined);
const next = new Array(max).fill(0);
const prev = new Array(max).fill(0);
const moveToTail = (index) => {
if (index === tail)
return;
const nextIndex = next[index];
if (index === head)
head = nextIndex;
else {
const prevIndex = prev[index];
next[prevIndex] = nextIndex;
prev[nextIndex] = prevIndex;
}
next[tail] = index;
prev[index] = tail;
tail = index;
};
map.set(key, node);
addNode(node);
if (size > max) evict();
};
const get = (key) => {
const node = map.get(key);
if (!node) return;
if (!refresh(key)) return;
if (head !== node) moveToHead(node);
return node.value;
};
const peek = (key) => {
var _a;
const node = map.get(key);
if (!node) return;
if (!refresh(key)) return;
if (node == null ? void 0 : node.timestamp) {
const now = Date.now();
const effectiveMaxAge = (_a = node.maxAge) != null ? _a : maxAge;
if (effectiveMaxAge && now - node.timestamp > effectiveMaxAge) {
del(key);
return;
}
}
return node.value;
};
const has = (key) => {
if (!refresh(key)) return false;
return map.has(key);
};
const keys = () => {
const result = [];
for (let current = head; current !== null; current = current.next) {
if (!refresh(current.key)) continue;
result.push(current.key);
}
return result;
};
const values = () => {
const result = [];
for (let current = head; current !== null; current = current.next) {
if (!refresh(current.key)) continue;
result.push(current.value);
}
return result;
};
const entries = () => {
const result = [];
for (let current = head; current !== null; current = current.next) {
if (!refresh(current.key)) continue;
result.push([current.key, current.value]);
}
return result;
};
const forEach = (callback) => {
for (let current = head; current !== null; current = current.next) {
if (!refresh(current.key)) continue;
callback(current.value, current.key);
}
};
const del = (key) => {
const node = map.get(key);
if (!node) return false;
if (node.maxAge && maxAgeCount > 0) {
maxAgeCount--;
}
removeNode(node);
map.delete(key);
if (dispose) dispose(node.value, key);
return true;
};
const clear = () => {
if (dispose) for (const node of map.values()) dispose(node.value, node.key);
map.clear();
head = tail = null;
size = 0;
maxAgeCount = 0;
};
const resize = (newMax) => {
max = newMax;
for (let i = size; i > max; i--) evict();
};
const available = () => {
refresh();
return max - map.size;
};
const stored = () => {
refresh();
return map.size;
};
const maxSize = () => max;
return {
/** Adds a key-value pair to the cache. Updates the value if the key already exists. */
set,
/** Retrieves the value for a given key and moves the key to the most recent position. */
get,
/** Retrieves the value for a given key without changing its position in the cache. */
peek,
/** Checks if a key exists in the cache. */
has,
/** Returns an array of all keys in the cache, from most recent to least recent. */
keys,
/** Returns an array of all values in the cache, from most recent to least recent. */
values,
/** Returns an array of [key, value] pairs, from most recent to least recent. */
entries,
/** Iterates over each key-value pair in the cache, from most recent to least recent. */
forEach,
/** Deletes a key-value pair from the cache. */
del,
/** Evicts the oldest item or the specified number of the oldest items from the cache. */
evict,
/** Clears all key-value pairs from the cache. */
clear,
/** Resizes the cache to a new maximum size, evicting items if necessary. */
resize,
/** Returns the number of available slots in the cache before reaching the maximum size. */
available,
/** Returns the number of items currently stored in the cache. */
stored,
/** Returns the maximum number of items that can be stored in the cache. */
maxSize
};
const _evict = () => {
const evictHead = head;
const key = keyList[evictHead];
onEviction === null || onEviction === void 0 ? void 0 : onEviction(valList[evictHead], key);
keyMap.delete(key);
keyList[evictHead] = undefined;
valList[evictHead] = undefined;
head = next[evictHead];
size--;
return evictHead;
};
return {
/** Adds a key-value pair to the cache. Updates the value if the key already exists. */
set(key, value) {
let index = keyMap.get(key);
if (index === undefined) {
index = size === max ? _evict() : free.length > 0 ? free.pop() : size;
keyMap.set(key, index);
keyList[index] = key;
size++;
}
else
onEviction === null || onEviction === void 0 ? void 0 : onEviction(valList[index], key);
valList[index] = value;
moveToTail(index);
},
/** Retrieves the value for a given key and moves the key to the most recent position. */
get(key) {
const index = keyMap.get(key);
if (index === undefined)
return;
moveToTail(index);
return valList[index];
},
/** Retrieves the value for a given key without changing its position. */
peek: (key) => {
const index = keyMap.get(key);
return index !== undefined ? valList[index] : undefined;
},
/** Checks if a key exists in the cache. */
has: (key) => keyMap.has(key),
/** Iterates over all keys in the cache, from least recent to most recent. */
*keys() {
let current = head;
for (let i = 0; i < size; i++) {
yield keyList[current];
current = next[current];
}
},
/** Iterates over all values in the cache, from least recent to most recent. */
*values() {
let current = head;
for (let i = 0; i < size; i++) {
yield valList[current];
current = next[current];
}
},
/** Iterates over `[key, value]` pairs in the cache, from least recent to most recent. */
*entries() {
let current = head;
for (let i = 0; i < size; i++) {
yield [keyList[current], valList[current]];
current = next[current];
}
},
/** Iterates over each key-value pair in the cache, from most recent to least recent. */
forEach: (callback) => {
let current = head;
for (let i = 0; i < size; i++) {
const key = keyList[current];
const value = valList[current];
callback(value, key);
current = next[current];
}
},
/** Deletes a key-value pair from the cache. */
delete(key) {
const index = keyMap.get(key);
if (index !== undefined) {
onEviction === null || onEviction === void 0 ? void 0 : onEviction(valList[index], key);
keyMap.delete(key);
free.push(index);
keyList[index] = undefined;
valList[index] = undefined;
size--;
return true;
}
return false;
},
/** Evicts the oldest item or the specified number of the oldest items from the cache. */
evict: (number) => {
let toPrune = Math.min(number, size);
while (toPrune > 0) {
_evict();
toPrune--;
}
},
/** Clears all key-value pairs from the cache. */
clear() {
for (const index of keyMap.values())
onEviction === null || onEviction === void 0 ? void 0 : onEviction(valList[index], keyList[index]);
keyMap.clear();
keyList.fill(undefined);
valList.fill(undefined);
free = [];
size = 0;
head = tail = 0;
},
/** Resizes the cache to a new maximum size, evicting items if necessary. */
resize: (newMax) => {
if (!(Number.isInteger(newMax) && newMax > 0))
throw new TypeError('`max` must be a positive integer');
max = newMax;
while (size > max)
_evict();
},
/** Returns the maximum number of items that can be stored in the cache. */
get max() {
return max;
},
/** Returns the number of items currently stored in the cache. */
get size() {
return size;
},
/** Returns the number of currently available slots in the cache before reaching the maximum size. */
get available() {
return max - size;
},
};
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
createLRU
});
exports.createLRU = createLRU;
{
"name": "lru.min",
"version": "0.1.0",
"description": "πŸ”₯ Extremely fast LRU cache for JavaScript (Browser compatible) β€” 6.1KB.",
"version": "0.2.0",
"description": "πŸ”₯ An extremely fast and efficient LRU cache for JavaScript (Browser compatible) β€” 4.8KB.",
"main": "./lib/index.js",

@@ -34,5 +34,4 @@ "module": "./lib/index.mjs",

"build:browser": "tsx tools/browserfy.ts",
"build:cjs": "esbuild src/index.ts --outfile=lib/index.js --platform=node --target=node8 --format=cjs",
"build:esm": "esbuild src/index.ts --outfile=lib/index.mjs --platform=node --target=node12 --format=esm",
"build": "tsc && npm run build:cjs && npm run build:esm && npm run build:browser",
"build": "tsc && npm run build:esm && npm run build:browser",
"test:node": "poku --node -p",

@@ -72,3 +71,2 @@ "test:bun": "poku --bun -p",

"lru",
"mru",
"cache",

@@ -75,0 +73,0 @@ "caching",

<h1 align="center">lru.min</h1>
<div align="center">
πŸ”₯ Extremely fast <strong>LRU Cache</strong> for <strong>JavaScript</strong> (<strong>Browser</strong> compatible) β€” **6.1KB**.
πŸ”₯ An extremely fast and efficient <strong><a href="https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29">LRU</a> Cache</strong> for <strong>JavaScript</strong> (<strong>Browser</strong> compatible) β€” **4.8KB**.
</div>
>
## Why

@@ -12,15 +14,10 @@

- **lru.min** ensures is fully compatible with both **Node.js** _(8+)_, **Bun**, **Deno** and, browser environments.<br />
- **lru.min** ensures is fully compatible with both **Node.js** _(8+)_, **Bun**, **Deno** and, browser environments.
#### πŸ‘¨πŸ»β€πŸ’» Features
πŸŽ–οΈ Performance
- πŸ•’ Smart and dynamic **TTL**.
- 🧹 Efficient **disposal** handling.
- βœ… Truly respects the maximum **cache size**.
- πŸ”‘ Take full caching control _(highly debuggable)_.
- [Check comparisons between **Node.js**, **Bun** and **Deno**](#performance).
#### πŸŽ–οΈ [Performance](#performance)
> Note that although performance is indeed important, the main purpose behind **lru.min** is the high compatibility level.
- **lru.min** has beaten the two most used and popular **LRU** packages.
---

@@ -50,3 +47,3 @@

> - ⚠️ Please wait until `v1.x.x` before using this package.
> - πŸ“˜ Complete documentation an public repository coming soon.
> - πŸ“˜ Public repository coming soon.

@@ -73,39 +70,205 @@ ### Import

### Create a new LRU Cache
> Set maximum size when creating **LRU**.
```ts
import { createLRU } from 'lru.min';
const LRU = createLRU({ max: 1000 });
```
Also, you can set a callback for every deletion:
```ts
const LRU = createLRU({
max: 1000,
dispose: (key, value) => {
// do something
},
});
```
### Set a cache
Adds a key-value pair to the cache. Updates the value if the key already exists
```ts
LRU.set('key', 'value');
```
### Get a cache
Retrieves the value for a given key and moves the key to the most recent position.
```ts
LRU.get('key');
```
### Peek a cache
Retrieves the value for a given key without changing its position.
```ts
LRU.get('key');
```
### Check if a key exists
```ts
LRU.has('key');
```
### Delete a cache
```ts
LRU.delete('key');
```
### Evict from the oldest cache
Evicts the specified number of the oldest items from the cache.
```ts
LRU.evict(10);
```
### Resize the cache
Resizes the cache to a new maximum size, evicting items if necessary.
```ts
LRU.resize(500);
```
### Clear the cache
Clears and disposes (if used) all key-value pairs from the cache.
```ts
LRU.clear();
```
### Debugging
#### Get the max size of the cache
```ts
LRU.max;
```
#### Get the current size of the cache
```ts
LRU.size;
```
#### Get the available slots in the cache
```ts
LRU.available;
```
#### Get all keys
Iterates over all keys in the cache, from least recent to most recent.
```ts
const keys = [...LRU.keys()];
```
#### Get all values
Iterates over all values in the cache, from least recent to most recent.
```ts
const keys = [...LRU.values()];
```
#### Get all entries
Iterates over `[key, value]` pairs in the cache, from least recent to most recent.
```ts
const entries = [...LRU.entries()];
```
#### Get all entries
Iterates over `[key, value]` pairs in the cache, from least recent to most recent.
```ts
const entries = [...LRU.entries()];
```
#### Run a callback for each entry
Iterates over each key-value pair in the cache, from most recent to least recent.
```ts
LRU.forEach((key, value) => {
// do something
});
```
---
## Performance
### Performance
In **Bun**, lru.min achieves up to **11** more operations per second than [**lru-cache**](https://github.com/isaacs/node-lru-cache) `v11.x.x` and up to **5** more ops per second than [**quick-lru**](https://github.com/sindresorhus/quick-lru) `v7.x.x` for essential usage (_get_, _set_, _evict_, and _delete_ the cache):
The benchmark is performed by comparing `1,000,000` runs through a maximum cache limit of `100,000`, getting `333,333` caches and delenting `200,000` keys 10 consecutive times, clearing the cache every run.
> You can see how the tests are run and compared in the [benchmark](https://github.com/wellwelwel/lru.min/tree/main/benchmark) directory.
>
> - [**lru-cache**](https://github.com/isaacs/node-lru-cache) `v11.0.0`
> - [**quick-lru**](https://github.com/sindresorhus/quick-lru) `v7.0.0`
#### Node.js
```sh
# Total Number of Cores: 24 (16 performance and 8 efficiency)
# Memory: 64 GB
# ES Modules
lru.min: 247.45ms
lru-cache: 255.93ms
quick-lru: 312.90ms
```
β€Ί Node.js
lru-cache x 24.42 ops/sec β€” Β±0.76% (45 runs sampled)
quick-lru x 25.62 ops/sec β€” Β±0.33% (47 runs sampled)
lru.min x 26.28 ops/sec β€” Β±0.19% (48 runs sampled)
```sh
# CommonJS
lru.min: 236.35ms
lru-cache: 258.74ms
quick-lru: not compatible
```
πŸš€ Fastest is lru.min
#### Bun
β€Ί Bun
lru-cache x 97.75 ops/sec β€” Β±0.32% (85 runs sampled)
quick-lru x 105.72 ops/sec β€” Β±0.33% (79 runs sampled)
lru.min x 110.08 ops/sec β€” Β±0.34% (82 runs sampled)
```sh
# ES Modules
lru.min: 298.42ms
quick-lru: 315.37ms
lru-cache: 359.23ms
```
πŸš€ Fastest is lru.min
```sh
# CommonJS
lru.min: 363.79ms
lru-cache: 371.39ms
quick-lru: not compatible
```
β€Ί Deno
lru-cache x 52.79 ops/sec β€” Β±0.38% (70 runs sampled)
quick-lru x 54.23 ops/sec β€” Β±0.34% (71 runs sampled)
lru.min x 56.39 ops/sec β€” Β±0.33% (74 runs sampled)
#### Deno
πŸš€ Fastest is lru.min
```sh
# ES Modules
lru.min: 222.60ms
lru-cache: 227.80ms
quick-lru: 253.00ms
```
- You can see how the tests are run and compared in the [benchmark](https://github.com/wellwelwel/lru.min/tree/main/benchmark) directory.
- **lru.min** is [continuously tested](https://github.com/wellwelwel/lru.min/blob/main/.github/workflows/ci_benchmark.yml) to ensure the above expectations.
[**lru-cache**](https://github.com/isaacs/node-lru-cache) `v11.x.x`
<!--
---
## Security Policy
Please check the [**SECURITY.md**](https://github.com/wellwelwel/lru.min/blob/main/SECURITY.md).
---

@@ -115,4 +278,21 @@

[![Contributors](https://img.shields.io/github/contributors/wellwelwel/lru.min?label=Contributors)](https://github.com/wellwelwel/lru.min/graphs/contributors)
> **lru.min** is based on the architecture and code of [**lru-cache**](https://github.com/isaacs/node-lru-cache) and [**quick-lru**](https://github.com/sindresorhus/quick-lru), simplifying their core concepts for enhanced performance and compatibility.
>
> For more comprehensive features such as **TTL** support, consider using and supporting them 🀝
-->
- [@isaacs](https://github.com/isaacs) and [lru-cache](https://github.com/isaacs/node-lru-cache).
- [@sindresorhus](https://github.com/sindresorhus) and [quick-lru](https://github.com/sindresorhus/quick-lru).
- [![Contributors](https://img.shields.io/github/contributors/wellwelwel/lru.min?label=Contributors)](https://github.com/wellwelwel/lru.min/graphs/contributors)
---
## License
**lru.min** is under the [**MIT License**](https://github.com/wellwelwel/lru.min/blob/main/LICENSE).<br />
Copyright Β© 2024-present [Weslley AraΓΊjo](https://github.com/wellwelwel) and **lru.min** [contributors](https://github.com/wellwelwel/lru.min/graphs/contributors).
**lru-cache** is licensed under the [**ISC License**](https://github.com/isaacs/node-lru-cache/blob/main/LICENSE).<br />
Copyright Β© 2010-2023 Isaac Z. Schlueter and Contributors.
**quick-lru** is licensed under the [**MIT License**](https://github.com/sindresorhus/quick-lru/blob/main/license).<br />
Copyright Β© Sindre Sorhus.

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚑️ by Socket Inc