99 lines
3.5 KiB
JavaScript
99 lines
3.5 KiB
JavaScript
|
|
import { CondensedGraph } from '../src/core/CondensedGraph.js';
|
||
|
|
import { performance } from 'node:perf_hooks';
|
||
|
|
|
||
|
|
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') || 200000);
|
||
|
|
const users = Number(args.get('users') || 10000);
|
||
|
|
const docs = Number(args.get('docs') || 50000);
|
||
|
|
const queryCount = Number(args.get('queries') || 10000);
|
||
|
|
|
||
|
|
console.log('CondensedGraph load bench');
|
||
|
|
console.log(` edges: ${edges}`);
|
||
|
|
console.log(` users: ${users}`);
|
||
|
|
console.log(` docs: ${docs}`);
|
||
|
|
console.log(` queries: ${queryCount}`);
|
||
|
|
|
||
|
|
const graph = new CondensedGraph();
|
||
|
|
const buildStart = performance.now();
|
||
|
|
for (let i = 0; i < edges; i++) {
|
||
|
|
graph.addEdge(
|
||
|
|
`user:${i % users}`,
|
||
|
|
['owner', 'editor', 'viewer'][i % 3],
|
||
|
|
`doc:${i % docs}`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
const buildTime = performance.now() - buildStart;
|
||
|
|
|
||
|
|
const finalizeStart = performance.now();
|
||
|
|
graph.finalizePerfectHash();
|
||
|
|
graph.finalizeWaveletAdjacency({ dropAdjacencyList: true });
|
||
|
|
const finalizeTime = performance.now() - finalizeStart;
|
||
|
|
|
||
|
|
const serializeStart = performance.now();
|
||
|
|
const buffer = graph.toBinary();
|
||
|
|
const serializeTime = performance.now() - serializeStart;
|
||
|
|
|
||
|
|
const heapBeforeLoad = process.memoryUsage().heapUsed;
|
||
|
|
const loadStart = performance.now();
|
||
|
|
const loaded = CondensedGraph.fromBinary(buffer);
|
||
|
|
const loadTime = performance.now() - loadStart;
|
||
|
|
const heapAfterLoad = process.memoryUsage().heapUsed;
|
||
|
|
|
||
|
|
const usersArr = Array.from({ length: users }, (_, i) => `user:${i}`);
|
||
|
|
const docsArr = Array.from({ length: docs }, (_, i) => `doc:${i}`);
|
||
|
|
|
||
|
|
const queryStart = performance.now();
|
||
|
|
let hits = 0;
|
||
|
|
for (let i = 0; i < queryCount; i++) {
|
||
|
|
const user = usersArr[i % users];
|
||
|
|
const doc = docsArr[i % docs];
|
||
|
|
const owner = loaded.findEdge(user, 'owner', doc);
|
||
|
|
const editor = loaded.findEdge(user, 'editor', doc);
|
||
|
|
const viewer = loaded.findEdge(user, 'viewer', doc);
|
||
|
|
if (owner !== null || editor !== null || viewer !== null) hits++;
|
||
|
|
}
|
||
|
|
const queryTime = performance.now() - queryStart;
|
||
|
|
const heapAfterQueries = process.memoryUsage().heapUsed;
|
||
|
|
|
||
|
|
const stats = loaded.getStats();
|
||
|
|
const bufferBytes = buffer.byteLength;
|
||
|
|
const heapDeltaLoadBytes = heapAfterLoad - heapBeforeLoad;
|
||
|
|
const heapDeltaQueryBytes = heapAfterQueries - heapAfterLoad;
|
||
|
|
const toMb = (bytes) => (bytes / 1024 / 1024).toFixed(2);
|
||
|
|
|
||
|
|
console.log('\nResults');
|
||
|
|
console.log(` build time: ${buildTime.toFixed(2)} ms`);
|
||
|
|
console.log(` finalize time: ${finalizeTime.toFixed(2)} ms`);
|
||
|
|
console.log(` serialize time: ${serializeTime.toFixed(2)} ms`);
|
||
|
|
console.log(` load time: ${loadTime.toFixed(2)} ms`);
|
||
|
|
console.log(` snapshot size: ${(bufferBytes / 1024 / 1024).toFixed(2)} MB`);
|
||
|
|
console.log(` heap delta (load): ${toMb(heapDeltaLoadBytes)} MB`);
|
||
|
|
console.log(` heap delta (post-query): ${toMb(heapDeltaQueryBytes)} MB`);
|
||
|
|
console.log(` bytes/edge (snapshot): ${(bufferBytes / edges).toFixed(2)}`);
|
||
|
|
console.log(` stats bytes/edge: ${stats.bytesPerEdge.toFixed(2)}`);
|
||
|
|
console.log(` query time: ${queryTime.toFixed(2)} ms`);
|
||
|
|
console.log(` avg query: ${(queryTime / queryCount * 1000).toFixed(3)} µs`);
|
||
|
|
console.log(` queries/sec: ${(queryCount / (queryTime / 1000)).toFixed(0)}`);
|
||
|
|
console.log(` hits: ${hits}`);
|