1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00

update benchmarks

This commit is contained in:
leibale
2021-12-07 11:01:42 -05:00
parent 12173e1cd7
commit b68f79538c
17 changed files with 248 additions and 91 deletions

1
benchmark/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.js.json

View File

@@ -0,0 +1,32 @@
version: 0.1
remote:
- type: oss-standalone
- setup: redis-small
setups:
- oss-standalone
spec:
setups:
- name: oss-standalone
type: oss-standalone
redis_topology:
primaries: 1
replicas: 0
resources:
requests:
cpus: "1"
memory: "10g"
exporter:
output_path: "./*.js.json"
redistimeseries:
timemetric: "$.timestamp"
metrics:
- "$.p0"
- "$.p50"
- "$.p95"
- "$.p99"
- "$.p100"
- "$.operationsPerSecond"

View File

@@ -4,6 +4,7 @@ import { promises as fs } from 'fs';
import { fork } from 'child_process'; import { fork } from 'child_process';
import { URL, fileURLToPath } from 'url'; import { URL, fileURLToPath } from 'url';
import { once } from 'events'; import { once } from 'events';
import { extname } from 'path';
async function getPathChoices() { async function getPathChoices() {
const dirents = await fs.readdir(new URL('.', import.meta.url), { const dirents = await fs.readdir(new URL('.', import.meta.url), {
@@ -32,11 +33,23 @@ async function getName() {
} }
const runnerPath = fileURLToPath(new URL('runner.js', import.meta.url)), const runnerPath = fileURLToPath(new URL('runner.js', import.meta.url)),
path = new URL(`${await getName()}/`, import.meta.url), path = new URL(`${await getName()}/`, import.meta.url);
metadata = await import(new URL('index.js', path));
async function getMetadata() {
try {
return await import(new URL('index.js', path));
} catch (err) {
if (err.code === 'ERR_MODULE_NOT_FOUND') return;
throw err;
}
}
const metadata = await getMetadata(),
timestamp = Date.now();
for (const file of await fs.readdir(path)) { for (const file of await fs.readdir(path)) {
if (file === 'index.js') continue; if (file === 'index.js' || extname(file) !== '.js') continue;
const benchmarkProcess = fork(runnerPath, [ const benchmarkProcess = fork(runnerPath, [
...argv, ...argv,
@@ -45,6 +58,9 @@ for (const file of await fs.readdir(path)) {
]); ]);
await once(benchmarkProcess, 'message'); await once(benchmarkProcess, 'message');
benchmarkProcess.send(metadata); benchmarkProcess.send({
metadata,
timestamp
});
await once(benchmarkProcess, 'close'); await once(benchmarkProcess, 'close');
} }

View File

@@ -0,0 +1,19 @@
import Redis from 'ioredis';
export default async (host) => {
const client = new Redis({
host,
lazyConnect: true
});
await client.connect();
return {
benchmark() {
return client.ping();
},
teardown() {
return client.disconnect();
}
}
};

View File

@@ -0,0 +1,9 @@
name: "ping"
clientconfig:
- command: |
npm install -ws
npm run build:tests-tools
cd benchmark
npm install
npm run start -- --name ping --redis-server-host ${server_private_ip}

21
benchmark/lib/ping/v3.js Normal file
View File

@@ -0,0 +1,21 @@
import { createClient } from 'redis-v3';
import { once } from 'events';
import { promisify } from 'util';
export default async (host) => {
const client = createClient({ host }),
pingAsync = promisify(client.ping).bind(client),
quitAsync = promisify(client.quit).bind(client);
await once(client, 'connect');
return {
benchmark() {
return pingAsync();
},
teardown() {
return quitAsync();
}
};
};

16
benchmark/lib/ping/v4.js Normal file
View File

@@ -0,0 +1,16 @@
import { createClient } from '@node-redis/client';
export default async (host) => {
const client = createClient({ host });
await client.connect();
return {
benchmark() {
return client.ping();
},
teardown() {
return client.disconnect();
}
};
};

View File

@@ -1,10 +1,11 @@
import yargs from 'yargs'; import yargs from 'yargs';
import { hideBin } from 'yargs/helpers'; import { hideBin } from 'yargs/helpers';
import { basename } from 'path'; import { basename } from 'path';
import { promises as fs } from 'fs';
import * as hdr from 'hdr-histogram-js'; import * as hdr from 'hdr-histogram-js';
hdr.initWebAssemblySync(); hdr.initWebAssemblySync();
const { path, times, concurrency } = yargs(hideBin(process.argv)) const { path, times, concurrency, 'redis-server-host': host } = yargs(hideBin(process.argv))
.option('path', { .option('path', {
type: 'string', type: 'string',
demandOption: true demandOption: true
@@ -19,25 +20,19 @@ const { path, times, concurrency } = yargs(hideBin(process.argv))
default: 100, default: 100,
demandOption: true demandOption: true
}) })
.option('redis-server-host', {
type: 'string'
})
.parseSync(); .parseSync();
async function setup() { const [ { metadata, timestamp }, module ] = await Promise.all([
const module = await import(path); new Promise(resolve => {
await module.setup(); process.once('message', resolve);
return module; process.send('ready');
} }),
import(path)
function getMetadata() { ]),
return new Promise(resolve => { { benchmark, teardown } = await module.default(host, metadata);
process.once('message', resolve);
process.send('ready');
});
}
const [ { benchmark, teardown }, metadata ] = await Promise.all([
setup(),
getMetadata()
]);
async function run(times) { async function run(times) {
return new Promise(resolve => { return new Promise(resolve => {
@@ -45,23 +40,20 @@ async function run(times) {
let num = 0, let num = 0,
inProgress = 0; inProgress = 0;
function run() { async function run() {
++inProgress; ++inProgress;
++num; ++num;
const start = process.hrtime.bigint(); const start = process.hrtime.bigint();
benchmark(metadata) await benchmark(metadata);
.catch(err => console.error(err)) histogram.recordValue(Number(process.hrtime.bigint() - start));
.finally(() => { --inProgress;
histogram.recordValue(Number(process.hrtime.bigint() - start));
--inProgress;
if (num < times) { if (num < times) {
run(); run();
} else if (inProgress === 0) { } else if (inProgress === 0) {
resolve(histogram); resolve(histogram);
} }
});
} }
const toInitiate = Math.min(concurrency, times); const toInitiate = Math.min(concurrency, times);
@@ -75,8 +67,20 @@ async function run(times) {
await run(Math.min(times * 0.1, 10_000)); await run(Math.min(times * 0.1, 10_000));
// benchmark // benchmark
const histogram = await run(times); const benchmarkStart = process.hrtime.bigint(),
histogram = await run(times),
benchmarkNanoseconds = process.hrtime.bigint() - benchmarkStart,
json = {
timestamp,
operationsPerSecond: times / Number(benchmarkNanoseconds) * 1_000_000_000,
p0: histogram.getValueAtPercentile(0),
p50: histogram.getValueAtPercentile(50),
p95: histogram.getValueAtPercentile(95),
p99: histogram.getValueAtPercentile(99),
p100: histogram.getValueAtPercentile(100)
};
console.log(`[${basename(path)}]:`); console.log(`[${basename(path)}]:`);
console.table(histogram.toJSON()); console.table(json);
await fs.writeFile(`${path}.json`, JSON.stringify(json));
await teardown(); await teardown();

View File

@@ -0,0 +1,9 @@
name: "set-get-delete-string-1KB"
clientconfig:
- command: |
npm install -ws
npm run build:tests-tools
cd benchmark
npm install
npm run start -- --name set-get-delete-string --size 1024 --redis-server-host ${server_private_ip}

View File

@@ -0,0 +1,9 @@
name: "set-get-delete-string-1MB"
clientconfig:
- command: |
npm install -ws
npm run build:tests-tools
cd benchmark
npm install
npm run start -- --name set-get-delete-string --size 1048576 --redis-server-host ${server_private_ip}

View File

@@ -0,0 +1,9 @@
name: "set-get-delete-string-8B"
clientconfig:
- command: |
npm install -ws
npm run build:tests-tools
cd benchmark
npm install
npm run start -- --name set-get-delete-string --size 8 --redis-server-host ${server_private_ip}

View File

@@ -1,19 +1,23 @@
import Redis from 'ioredis'; import Redis from 'ioredis';
const client = new Redis({ lazyConnect: true }); export default async (host, { randomString }) => {
const client = new Redis({
host,
lazyConnect: true
});
export function setup() { await client.connect();
return client.connect();
}
export function benchmark({ randomString }) { return {
return Promise.all([ benchmark() {
client.set(randomString, randomString), return Promise.all([
client.get(randomString), client.set(randomString, randomString),
client.del(randomString) client.get(randomString),
]); client.del(randomString)
} ]);
},
export function teardown() { teardown() {
return client.disconnect(); return client.disconnect();
} }
}
};

View File

@@ -1,19 +0,0 @@
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

@@ -1,19 +0,0 @@
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();
}

View File

@@ -0,0 +1,27 @@
import { createClient } from 'redis-v3';
import { once } from 'events';
import { promisify } from 'util';
export default async (host, { randomString }) => {
const client = createClient({ host }),
setAsync = promisify(client.set).bind(client),
getAsync = promisify(client.get).bind(client),
delAsync = promisify(client.del).bind(client),
quitAsync = promisify(client.quit).bind(client);
await once(client, 'connect');
return {
benchmark() {
return Promise.all([
setAsync(randomString, randomString),
getAsync(randomString),
delAsync(randomString)
]);
},
teardown() {
return quitAsync();
}
};
};

View File

@@ -0,0 +1,20 @@
import { createClient } from '@node-redis/client';
export default async (host, { randomString }) => {
const client = createClient({ host });
await client.connect();
return {
benchmark() {
return Promise.all([
client.set(randomString, randomString),
client.get(randomString),
client.del(randomString)
]);
},
teardown() {
return client.disconnect();
}
};
};

View File

@@ -7,8 +7,7 @@
"start": "node ." "start": "node ."
}, },
"dependencies": { "dependencies": {
"@node-redis/client-local": "../packages/client", "@node-redis/client": "../packages/client",
"@node-redis/client-production": "npm:@node-redis/client@1.0.0",
"hdr-histogram-js": "2.0.1", "hdr-histogram-js": "2.0.1",
"ioredis": "4.28.1", "ioredis": "4.28.1",
"redis-v3": "npm:redis@3.1.2", "redis-v3": "npm:redis@3.1.2",