Worker-owned reconciliation commits

This commit is contained in:
2026-10-21 11:07:36 -04:00
parent a127a40293
commit 7b6873921a
10 changed files with 322 additions and 52 deletions
+15 -9
View File
@@ -15,6 +15,7 @@ const text = process.argv[2] ?? '10000';
if (!/^[1-9]\d{0,5}$/.test(text) || Number(text) > 100000) throw new Error('Fixture size must be 1..100000 orders');
const count = Number(text), scenario = process.argv[3] ?? 'terminal';
if (!['terminal', 'confirmed-delivery'].includes(scenario)) throw new Error('Scenario must be terminal or confirmed-delivery');
const workerEnabled = process.argv[4] === 'worker';
const directory = await mkdtemp(join(tmpdir(), 'wikideck-market-reconciliation-'));
const streamId = randomUUID(), tip = 'a'.repeat(64);
const deliveryRows = new Map<string, { height: number; blockHash: string }>();
@@ -33,7 +34,7 @@ try {
events: [], cursor: after, head: 0, caughtUp: true }),
submitTransfer: async () => { throw new Error('Benchmark never submits transfers'); },
};
market = await Market.open(directory, chain, { feeBps: 250, confirmations: 2 });
market = await Market.open(directory, chain, { feeBps: 250, confirmations: 2 }, Date.now, { worker: workerEnabled });
const db = new DatabaseSync(join(directory, NETWORK.includes('mainnet') ? 'mainnet' : 'testnet', 'market.sqlite'));
try {
const insertListing = db.prepare('INSERT INTO listings(id,card,status,data) VALUES(?,?,?,?)');
@@ -62,25 +63,30 @@ try {
} finally { db.close(); }
const latencies: number[] = [];
const maxPasses = Math.ceil(count / MARKET_RECONCILIATION_BATCH_SIZE) * 2 + 4;
const deadline = Date.now() + Math.max(30_000, count * 20);
const eventLoopDelay = monitorEventLoopDelay({ resolution: 10 });
eventLoopDelay.enable();
const start = performance.now();
let started = false;
try {
for (let pass = 0; pass < maxPasses && (pass === 0 || market.hasReconciliationBacklog()); pass++) {
const before = performance.now();
market.browse();
latencies.push(performance.now() - before);
while (Date.now() < deadline && (!started || market.hasReconciliationBacklog() || market.isReconciliationWorkerBusy())) {
if (!workerEnabled || !market.isReconciliationWorkerBusy()) {
const before = performance.now();
market.browse();
latencies.push(performance.now() - before);
started = true;
}
await yieldToEventLoop(); // Permit the delay monitor to observe synchronous batch stalls.
if (workerEnabled && market.isReconciliationWorkerBusy()) await new Promise(resolve => setTimeout(resolve, 1));
}
} finally { eventLoopDelay.disable(); }
const elapsedMs = performance.now() - start;
if (market.hasReconciliationBacklog()) throw new Error(`Reconciliation did not finish within ${maxPasses} bounded passes`);
market.close(); market = undefined;
if (!started || market.hasReconciliationBacklog() || market.isReconciliationWorkerBusy()) throw new Error('Reconciliation did not finish before benchmark deadline');
await market.close(); market = undefined;
const bytes = (await stat(join(directory, NETWORK.includes('mainnet') ? 'mainnet' : 'testnet', 'market.sqlite'))).size;
latencies.sort((a, b) => a - b);
const percentile = (p: number) => latencies[Math.min(latencies.length - 1, Math.ceil(latencies.length * p) - 1)];
console.log(JSON.stringify({ fixture: `synthetic-${scenario}-orders-and-listings`, orders: count, listings: count,
console.log(JSON.stringify({ fixture: `synthetic-${scenario}-orders-and-listings`, workerEnabled, orders: count, listings: count,
batchSizePerTable: MARKET_RECONCILIATION_BATCH_SIZE, reconciliationPasses: latencies.length, elapsedMs,
rowsPerSecond: Math.round((count * 2 * 1000) / elapsedMs), passLatencyP50Ms: percentile(0.50),
passLatencyP95Ms: percentile(0.95), passLatencyMaxMs: latencies.at(-1), sqliteBytes: bytes,
+1
View File
@@ -0,0 +1 @@
// Temporary runtime probe removed after verification.