Files
core/benchmarks/condensed-graph-load-bench.js
T
John Dvorak 717ae1031e initial commit: @arbiter/core authorization engine with js-rigor hardening
Zanzibar-style authorization graph engine (direct/chain/TTU/defeasible/
binary modes, condensed snapshots, value relations) with 39 rigor test
campaigns. Includes fixes for snapshot binary writer/reader format
mismatch (snapshot-of-snapshot corruption), possibility write-boundary
validation, empty-graph snapshot serialization, relation lookup cache
direction collision, config-redefinition cache invalidation, binary
threshold semantics, defeasible compiled routing, and comparator
reason whitelisting.
2026-07-31 13:44:06 -07:00

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