-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c4da22
commit 05e1c99
Showing
7 changed files
with
352 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Benchmark | ||
|
||
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. | ||
|
||
> - [**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 | ||
|
||
- ES Modules | ||
|
||
```sh | ||
# Time: | ||
lru.min: 240.45ms | ||
lru-cache: 258.32ms | ||
quick-lru: 279.89ms | ||
|
||
# CPU: | ||
lru.min: 275558.30µs | ||
lru-cache: 306858.30µs | ||
quick-lru: 401318.80µs | ||
``` | ||
|
||
- CommonJS | ||
|
||
```sh | ||
# Time: | ||
lru.min: 242.86ms | ||
lru-cache: 264.30ms | ||
quick-lru: not compatible | ||
|
||
# CPU: | ||
lru.min: 280118.00µs | ||
lru-cache: 310327.20µs | ||
quick-lru: not compatible | ||
``` | ||
|
||
#### Bun | ||
|
||
- ES Modules | ||
|
||
```sh | ||
# Time: | ||
lru.min: 298.42ms | ||
quick-lru: 315.37ms | ||
lru-cache: 359.23ms | ||
|
||
# CPU: | ||
lru.min: 401869.50µs | ||
quick-lru: 478517.40µs | ||
lru-cache: 510357.60µs | ||
``` | ||
|
||
- CommonJS | ||
|
||
```sh | ||
# Time: | ||
lru.min: 324.41ms | ||
lru-cache: 370.22ms | ||
quick-lru: not compatible | ||
|
||
# CPU: | ||
lru.min: 396790.50µs | ||
lru-cache: 488574.50µs | ||
quick-lru: not compatible | ||
``` | ||
|
||
#### Deno | ||
|
||
- ES Modules | ||
|
||
```sh | ||
# Time: | ||
lru.min: 222.60ms | ||
lru-cache: 227.80ms | ||
quick-lru: 253.00ms | ||
``` | ||
|
||
> **Deno** benchmarks were carried out without an isolated process. | ||
--- | ||
|
||
## Running | ||
|
||
To run the benchmark tests, follow these steps in the `./lru.min` directory: | ||
|
||
```sh | ||
npm ci | ||
npm run build | ||
npm run benchmark:esm | ||
npm run benchmark:cjs | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,42 @@ | ||
const { performance } = require('node:perf_hooks'); | ||
const { LRUCache } = require('lru-cache'); | ||
const { createLRU } = require('../lib/index.js'); | ||
const { fork } = require('node:child_process'); | ||
|
||
const benchmarks = ['lru-cache', 'lru.min']; | ||
const results = new Map(); | ||
|
||
const measurePerformance = (fn) => { | ||
const startTime = performance.now(); | ||
const runBenchmark = (benchmarkName) => { | ||
return new Promise((resolve) => { | ||
const child = fork('worker.cjs', [benchmarkName]); | ||
|
||
fn(); | ||
|
||
const endTime = performance.now(); | ||
|
||
return { | ||
time: endTime - startTime, | ||
}; | ||
}; | ||
|
||
const times = 10; | ||
const max = 100000; | ||
const brute = 1000000; | ||
|
||
const benchmark = (createCache) => { | ||
const cache = createCache(); | ||
const results = { time: 0 }; | ||
|
||
for (let i = 0; i < times; i++) { | ||
const result = measurePerformance(() => { | ||
for (let j = 0; j < brute; j++) { | ||
cache.set(`key-${j}`, j); | ||
|
||
if (j > 0 && j % 3 === 0) { | ||
const randomIndex = Math.floor(Math.random() * j); | ||
cache.get(`key-${randomIndex}`); | ||
} | ||
|
||
if (j > 0 && j % 5 === 0) { | ||
const randomIndex = Math.floor(Math.random() * j); | ||
cache.delete(`key-${randomIndex}`); | ||
} | ||
} | ||
child.on('message', (result) => { | ||
resolve(result); | ||
}); | ||
|
||
results.time += result.time; | ||
|
||
cache.clear(); | ||
} | ||
|
||
return { | ||
time: results.time / times, | ||
}; | ||
child.on('exit', () => { | ||
resolve(null); | ||
}); | ||
}); | ||
}; | ||
|
||
results.set( | ||
'lru-cache', | ||
benchmark(() => new LRUCache({ max })) | ||
); | ||
results.set( | ||
'lru.min', | ||
benchmark(() => createLRU({ max })) | ||
); | ||
|
||
const time = [...results.entries()].sort((a, b) => a[1].time - b[1].time); | ||
|
||
console.log('CommonJS'); | ||
(async () => { | ||
for (const benchmark of benchmarks) { | ||
const result = await runBenchmark(benchmark); | ||
results.set(benchmark, result); | ||
} | ||
|
||
for (const [name, result] of time) | ||
console.log(`${name}: ${result.time.toFixed(2)}ms`); | ||
console.log('quick-lru: not compatible'); | ||
const sortedByTime = [...results.entries()].sort( | ||
(a, b) => a[1].time - b[1].time | ||
); | ||
const sortedByCpu = [...results.entries()].sort( | ||
(a, b) => a[1].cpu - b[1].cpu | ||
); | ||
|
||
console.log('Time:'); | ||
for (const [name, result] of sortedByTime) | ||
console.log(` ${name}: ${result.time.toFixed(2)}ms`); | ||
console.log(' quick-lru: not compatible'); | ||
|
||
console.log('\nCPU:'); | ||
for (const [name, result] of sortedByCpu) | ||
console.log(` ${name}: ${result.cpu.toFixed(2)}µs`); | ||
console.log(' quick-lru: not compatible'); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,40 @@ | ||
import { performance } from 'node:perf_hooks'; | ||
import { LRUCache } from 'lru-cache'; | ||
import { createLRU } from '../lib/index.mjs'; | ||
import QuickLRU from 'quick-lru'; | ||
import { fork } from 'node:child_process'; | ||
|
||
const benchmarks = ['lru-cache', 'quick-lru', 'lru.min']; | ||
const results = new Map(); | ||
|
||
const measurePerformance = (fn) => { | ||
const startTime = performance.now(); | ||
const runBenchmark = (benchmarkName) => { | ||
return new Promise((resolve) => { | ||
const child = fork('worker.mjs', [benchmarkName]); | ||
|
||
fn(); | ||
|
||
const endTime = performance.now(); | ||
|
||
return { | ||
time: endTime - startTime, | ||
}; | ||
}; | ||
|
||
const times = 10; | ||
const max = 100000; | ||
const brute = 1000000; | ||
|
||
const benchmark = (createCache) => { | ||
const cache = createCache(); | ||
const results = { time: 0 }; | ||
|
||
for (let i = 0; i < times; i++) { | ||
const result = measurePerformance(() => { | ||
for (let j = 0; j < brute; j++) { | ||
cache.set(`key-${j}`, j); | ||
|
||
if (j > 0 && j % 3 === 0) { | ||
const randomIndex = Math.floor(Math.random() * j); | ||
cache.get(`key-${randomIndex}`); | ||
} | ||
|
||
if (j > 0 && j % 5 === 0) { | ||
const randomIndex = Math.floor(Math.random() * j); | ||
cache.delete(`key-${randomIndex}`); | ||
} | ||
} | ||
child.on('message', (result) => { | ||
resolve(result); | ||
}); | ||
|
||
results.time += result.time; | ||
|
||
cache.clear(); | ||
} | ||
|
||
return { | ||
time: results.time / times, | ||
}; | ||
child.on('exit', () => { | ||
resolve(null); | ||
}); | ||
}); | ||
}; | ||
|
||
results.set( | ||
'lru-cache', | ||
benchmark(() => new LRUCache({ max })) | ||
); | ||
results.set( | ||
'quick-lru', | ||
benchmark(() => new QuickLRU({ maxSize: max })) | ||
); | ||
results.set( | ||
'lru.min', | ||
benchmark(() => createLRU({ max })) | ||
); | ||
|
||
const time = [...results.entries()].sort((a, b) => a[1].time - b[1].time); | ||
|
||
console.log('ES Modules'); | ||
(async () => { | ||
for (const benchmark of benchmarks) { | ||
const result = await runBenchmark(benchmark); | ||
results.set(benchmark, result); | ||
} | ||
|
||
for (const [name, result] of time) | ||
console.log(`${name}: ${result.time.toFixed(2)}ms`); | ||
const sortedByTime = [...results.entries()].sort( | ||
(a, b) => a[1].time - b[1].time | ||
); | ||
const sortedByCpu = [...results.entries()].sort( | ||
(a, b) => a[1].cpu - b[1].cpu | ||
); | ||
|
||
console.log('Time:'); | ||
for (const [name, result] of sortedByTime) | ||
console.log(` ${name}: ${result.time.toFixed(2)}ms`); | ||
|
||
console.log('\nCPU:'); | ||
for (const [name, result] of sortedByCpu) | ||
console.log(` ${name}: ${result.cpu.toFixed(2)}µs`); | ||
})(); |
Oops, something went wrong.