1da6bc7842
- src/snapshot.js: compact portable wire (VGST store / VGGP graph), binary maps for params/pattern/objects (no JSON), buffer values (no JS bigint), CRC-32 guarded. - createFileStore: binary per-key files (encodeEntryBytes/decodeEntryBytes). - ValueGraph snapshot/snapshotFile/restore/loadFile; keys base64url(params-bytes). - 60 tests (node:test + rigor incl. 'flip ANY byte never decodes silently').
39 lines
1.9 KiB
JavaScript
39 lines
1.9 KiB
JavaScript
// Hotpath micro-benchmark: how fast is a value-graph `get` on the authorization
|
|
// hotpath? Compared against a plain Map lookup.
|
|
import { performance } from 'node:perf_hooks';
|
|
import { ValueGraph } from '../src/index.js';
|
|
|
|
function bench(name, fn, iterations = 200_000) {
|
|
for (let i = 0; i < 10_000; i++) fn(); // warmup
|
|
const t0 = performance.now();
|
|
for (let i = 0; i < iterations; i++) fn();
|
|
const ms = performance.now() - t0;
|
|
const nsPerOp = (ms * 1e6) / iterations;
|
|
const opsPerSec = Math.round((iterations / ms) * 1000);
|
|
console.log(`${name.padEnd(46)} ${nsPerOp.toFixed(0).padStart(8)} ns/op ${String(opsPerSec).padStart(10)} ops/sec`);
|
|
}
|
|
|
|
const vg = new ValueGraph();
|
|
vg.compute('balance', () => 1250);
|
|
await new Promise((res) => vg.get('u:1', 'balance', {}, (e, v) => res(v)));
|
|
const plan = vg.plan('u:1', 'balance', {}); // cached plan for the hot loop
|
|
|
|
const coldVg = new ValueGraph();
|
|
coldVg.compute('balance', () => 42);
|
|
|
|
vg.define('a', { operator: 'source', fn: () => 10 });
|
|
vg.define('b', { operator: 'source', fn: () => 20 });
|
|
vg.define('c', { operator: 'source', fn: () => 30 });
|
|
vg.define('risk', { operator: 'fusion:custom', parents: ['a', 'b', 'c'], weights: [0.6, 0.3, 0.1] });
|
|
await new Promise((res) => vg.get('u:1', 'risk', {}, (e, v) => res(v)));
|
|
|
|
const baseline = new Map([['u:1|balance|{}', 1250]]);
|
|
|
|
console.log('--- hotpath (authorization value lookup) ---');
|
|
bench('Map.get baseline', () => baseline.get('u:1|balance|{}'));
|
|
bench('vg.get cached (plan/run)', () => vg.run(plan, () => {}));
|
|
bench('vg.get cached (get + compile)', () => vg.get('u:1', 'balance', {}, () => {}));
|
|
bench('vg.get cold (fresh compute)', () => coldVg.get('x', 'balance', {}, () => {}));
|
|
bench('vg.get fusion:custom DAG', () => vg.get('u:1', 'risk', {}, () => {}));
|
|
bench('vg.query duplex {get}', () => { const q = vg.query('u:1', 'balance', {}); q.sink.write({ get: true }); q.sink.end(); });
|