Skip to content

Commit

Permalink
chore: improve benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
wellwelwel committed Aug 27, 2024
1 parent 8c4da22 commit 05e1c99
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 145 deletions.
72 changes: 52 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,45 +216,77 @@ The benchmark is performed by comparing `1,000,000` runs through a maximum cache
#### Node.js

- ES Modules

```sh
# ES Modules
lru.min: 247.45ms
lru-cache: 255.93ms
quick-lru: 312.90ms
# 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
# CommonJS
lru.min: 236.35ms
lru-cache: 258.74ms
quick-lru: not compatible
# 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
# ES Modules
lru.min: 298.42ms
quick-lru: 315.37ms
lru-cache: 359.23ms
# 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
# CommonJS
lru.min: 363.79ms
lru-cache: 371.39ms
quick-lru: not compatible
# 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
# ES Modules
lru.min: 222.60ms
lru-cache: 227.80ms
quick-lru: 253.00ms
# Time:
lru.min: 222.60ms
lru-cache: 227.80ms
quick-lru: 253.00ms
```

> **Deno** benchmarks were carried out without an isolated process.
---

## Security Policy
Expand Down
92 changes: 92 additions & 0 deletions benchmark/README.md
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
```
93 changes: 33 additions & 60 deletions benchmark/index.cjs
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');
})();
95 changes: 31 additions & 64 deletions benchmark/index.mjs
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`);
})();
Loading

0 comments on commit 05e1c99

Please sign in to comment.