1
0
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:
leibale
2021-12-01 20:17:52 -05:00
parent cba0289ff7
commit f55de0efbf
10 changed files with 916 additions and 8 deletions

51
benchmark/lib/index.js Normal file
View 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
View 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();

View 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');

View 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();
}

View 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();
}

View 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();
}