Files

110 lines
3.8 KiB
JavaScript
Raw Permalink Normal View History

import fs from 'node:fs';
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { CondensedGraph } from '../src/core/CondensedGraph.js';
import { ShardedSnapshotBuilder } from '../src/core/shards/ShardedSnapshotBuilder.js';
import { ShardedSnapshot } from '../src/core/shards/ShardedSnapshot.js';
import { FileShardStorage } from '../src/core/shards/FileShardStorage.js';
function parseArgs(argv) {
const args = new Map();
for (let i = 2; i < argv.length; i++) {
const value = argv[i];
if (!value.startsWith('--')) continue;
const [key, inline] = value.slice(2).split('=');
if (inline !== undefined) {
args.set(key, inline);
continue;
}
const next = argv[i + 1];
if (next && !next.startsWith('--')) {
args.set(key, next);
i++;
} else {
args.set(key, true);
}
}
return args;
}
const args = parseArgs(process.argv);
const edges = Number(args.get('edges') || 50000);
const users = Number(args.get('users') || 5000);
const docs = Number(args.get('docs') || 20000);
const bucketSize = Number(args.get('bucket') || 4096);
const samples = Number(args.get('samples') || 10000);
const output = args.get('output') || 'tmp/shards-bench';
console.log('Sharded snapshot bench');
console.log(` edges: ${edges}`);
console.log(` users: ${users}`);
console.log(` docs: ${docs}`);
console.log(` bucket: ${bucketSize}`);
console.log(` samples: ${samples}`);
const graph = new CondensedGraph();
const relations = ['owner', 'editor', 'viewer'];
const edgePairs = [];
const buildStart = performance.now();
for (let i = 0; i < edges; i++) {
const userIndex = i % users;
const docIndex = i % docs;
const relId = i % 3;
const srcId = graph._ensureNode(`user:${userIndex}`);
const dstId = graph._ensureNode(`doc:${docIndex}`);
graph.addEdge(srcId, relations[relId], dstId);
edgePairs.push({ srcId, dstId, relId });
}
const buildTime = performance.now() - buildStart;
graph.finalizePerfectHash();
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
const snapshot = graph.toBinary();
const snapshotPath = path.join(output, 'snapshot.bin');
fs.mkdirSync(output, { recursive: true });
fs.writeFileSync(snapshotPath, new Uint8Array(snapshot));
const shardStart = performance.now();
const builder = new ShardedSnapshotBuilder({ bucketSize, includeDirections: ['out'] });
const manifest = builder.build(graph, output);
const shardTime = performance.now() - shardStart;
const storage = new FileShardStorage(output);
const sharded = new ShardedSnapshot(manifest, storage, { cacheLimit: 8 });
sharded.initializeSync();
const srcIds = Array.from({ length: users }, (_, i) => i);
const dstIds = Array.from({ length: docs }, (_, i) => i + users);
const findStart = performance.now();
let hits = 0;
for (let i = 0; i < samples; i++) {
const pair = edgePairs[i % edgePairs.length];
const srcId = pair.srcId;
const dstId = pair.dstId;
const relId = pair.relId;
const edge = sharded.findEdgeSync(srcId, relId, dstId);
if (edge) hits++;
}
const findTime = performance.now() - findStart;
const outStart = performance.now();
let outEdges = 0;
for (let i = 0; i < samples; i++) {
const srcId = srcIds[i % srcIds.length];
const relId = i % 3;
const edgesOut = sharded.getOutEdgesSync(srcId, relId);
outEdges += edgesOut.length;
}
const outTime = performance.now() - outStart;
console.log('\nResults');
console.log(` build time: ${buildTime.toFixed(2)} ms`);
console.log(` shard time: ${shardTime.toFixed(2)} ms`);
console.log(` shards: ${manifest.shards.length}`);
console.log(` snapshot size: ${(snapshot.byteLength / 1024 / 1024).toFixed(2)} MB`);
console.log(` findEdge avg: ${(findTime / samples * 1000).toFixed(3)} µs`);
console.log(` getOutEdges avg: ${(outTime / samples * 1000).toFixed(3)} µs`);
console.log(` hits: ${hits}`);
console.log(` outEdges: ${outEdges}`);