You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
improve encodeCommand performance, add set-get-delete-string benchmark
This commit is contained in:
51
benchmark/lib/index.js
Normal file
51
benchmark/lib/index.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { promises as fs } from 'fs';
|
||||
import { fork } from 'child_process';
|
||||
import { URL, fileURLToPath } from 'url';
|
||||
import { once } from 'events';
|
||||
|
||||
async function getPathChoices() {
|
||||
const dirents = await fs.readdir(new URL('.', import.meta.url), {
|
||||
withFileTypes: true
|
||||
});
|
||||
|
||||
const choices = [];
|
||||
for (const dirent of dirents) {
|
||||
if (!dirent.isDirectory()) continue;
|
||||
|
||||
choices.push(dirent.name);
|
||||
}
|
||||
|
||||
return choices;
|
||||
}
|
||||
|
||||
const argv = hideBin(process.argv);
|
||||
|
||||
async function getName() {
|
||||
return yargs(argv)
|
||||
.option('name', {
|
||||
demandOption: true,
|
||||
choices: await getPathChoices()
|
||||
})
|
||||
.parseSync().name;
|
||||
}
|
||||
|
||||
|
||||
const runnerPath = fileURLToPath(new URL('runner.js', import.meta.url)),
|
||||
path = new URL(`${await getName()}/`, import.meta.url),
|
||||
metadata = await import(new URL('index.js', path));
|
||||
|
||||
for (const file of await fs.readdir(path)) {
|
||||
if (file === 'index.js') continue;
|
||||
|
||||
const benchmarkProcess = fork(runnerPath, [
|
||||
...argv,
|
||||
'--path',
|
||||
fileURLToPath(path) + file
|
||||
]);
|
||||
|
||||
await once(benchmarkProcess, 'message');
|
||||
benchmarkProcess.send(metadata);
|
||||
await once(benchmarkProcess, 'close');
|
||||
}
|
76
benchmark/lib/runner.js
Normal file
76
benchmark/lib/runner.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { basename } from 'path';
|
||||
|
||||
const { path, times, concurrency } = yargs(hideBin(process.argv))
|
||||
.option('path', {
|
||||
type: 'string',
|
||||
demandOption: true
|
||||
})
|
||||
.option('times', {
|
||||
type: 'number',
|
||||
default: 1_000_000,
|
||||
demandOption: true
|
||||
})
|
||||
.option('concurrency', {
|
||||
type: 'number',
|
||||
default: 100,
|
||||
demandOption: true
|
||||
})
|
||||
.parseSync();
|
||||
|
||||
async function setup() {
|
||||
const module = await import(path);
|
||||
await module.setup();
|
||||
return module;
|
||||
}
|
||||
|
||||
function getMetadata() {
|
||||
return new Promise(resolve => {
|
||||
process.once('message', resolve);
|
||||
process.send('ready');
|
||||
});
|
||||
}
|
||||
|
||||
const [ { benchmark, teardown }, metadata ] = await Promise.all([
|
||||
setup(),
|
||||
getMetadata()
|
||||
]);
|
||||
|
||||
async function run(times) {
|
||||
return new Promise(resolve => {
|
||||
let num = 0,
|
||||
inProgress = 0;
|
||||
|
||||
function run() {
|
||||
++inProgress;
|
||||
++num;
|
||||
benchmark(metadata)
|
||||
.catch(err => console.error(err))
|
||||
.finally(() => {
|
||||
--inProgress;
|
||||
|
||||
if (num < times) {
|
||||
run();
|
||||
} else if (inProgress === 0) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (let i = 0; i < concurrency; i++) {
|
||||
run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// warmup
|
||||
await run(Math.min(times * 0.1, 10_000));
|
||||
|
||||
// benchmark
|
||||
const start = process.hrtime.bigint();
|
||||
await run(times);
|
||||
const took = (process.hrtime.bigint() - start);
|
||||
console.log(`[${basename(path)}]: took ${took / 1_000_000n}ms, ${took / BigInt(times)}ns per operation`);
|
||||
|
||||
await teardown();
|
13
benchmark/lib/set-get-delete-string/index.js
Normal file
13
benchmark/lib/set-get-delete-string/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { randomBytes } from 'crypto';
|
||||
|
||||
const { size } = yargs(hideBin(process.argv))
|
||||
.option('size', {
|
||||
type: 'number',
|
||||
default: 1024,
|
||||
demandOption: true
|
||||
})
|
||||
.parseSync();
|
||||
|
||||
export const randomString = randomBytes(size).toString('ascii');
|
19
benchmark/lib/set-get-delete-string/ioredis.js
Normal file
19
benchmark/lib/set-get-delete-string/ioredis.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import Redis from 'ioredis';
|
||||
|
||||
const client = new Redis({ lazyConnect: true });
|
||||
|
||||
export function setup() {
|
||||
return client.connect();
|
||||
}
|
||||
|
||||
export function benchmark({ randomString }) {
|
||||
return Promise.all([
|
||||
client.set(randomString, randomString),
|
||||
client.get(randomString),
|
||||
client.del(randomString)
|
||||
]);
|
||||
}
|
||||
|
||||
export function teardown() {
|
||||
return client.disconnect();
|
||||
}
|
19
benchmark/lib/set-get-delete-string/local.js
Normal file
19
benchmark/lib/set-get-delete-string/local.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createClient } from '@node-redis/client-local';
|
||||
|
||||
const client = createClient();
|
||||
|
||||
export function setup() {
|
||||
return client.connect();
|
||||
}
|
||||
|
||||
export function benchmark({ randomString }) {
|
||||
return Promise.all([
|
||||
client.set(randomString, randomString),
|
||||
client.get(randomString),
|
||||
client.del(randomString)
|
||||
]);
|
||||
}
|
||||
|
||||
export function teardown() {
|
||||
return client.disconnect();
|
||||
}
|
19
benchmark/lib/set-get-delete-string/production.js
Normal file
19
benchmark/lib/set-get-delete-string/production.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createClient } from '@node-redis/client-production';
|
||||
|
||||
const client = createClient();
|
||||
|
||||
export function setup() {
|
||||
return client.connect();
|
||||
}
|
||||
|
||||
export function benchmark({ randomString }) {
|
||||
return Promise.all([
|
||||
client.set(randomString, randomString),
|
||||
client.get(randomString),
|
||||
client.del(randomString)
|
||||
]);
|
||||
}
|
||||
|
||||
export function teardown() {
|
||||
return client.disconnect();
|
||||
}
|
Reference in New Issue
Block a user