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}`);