import fs from 'node:fs'; 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; } function parseCsv(content) { const lines = content.split('\n').map(line => line.trim()).filter(Boolean); const data = []; for (const line of lines) { if (line.startsWith('b2c_auth_bench')) continue; if (line.startsWith('scenario,')) continue; const parts = line.split(','); if (parts.length < 11) continue; const [scenario, nodes, edges, buildMs, authMs, authQps, precision, recall, f1, p95, p99] = parts; data.push({ scenario, nodes: Number(nodes), edges: Number(edges), buildMs: Number(buildMs), authMs: Number(authMs), authQps: Number(authQps), precision: Number(precision), recall: Number(recall), f1: Number(f1), p95: Number(p95), p99: Number(p99) }); } return data; } function fitPowerLaw(points, field) { const samples = points.filter(point => point[field] > 0 && point.nodes > 0); if (samples.length < 2) return null; const xs = samples.map(point => Math.log(point.nodes)); const ys = samples.map(point => Math.log(point[field])); const n = xs.length; const sumX = xs.reduce((acc, value) => acc + value, 0); const sumY = ys.reduce((acc, value) => acc + value, 0); const sumXY = xs.reduce((acc, value, index) => acc + value * ys[index], 0); const sumX2 = xs.reduce((acc, value) => acc + value * value, 0); const denom = n * sumX2 - sumX * sumX; if (denom === 0) return null; const slope = (n * sumXY - sumX * sumY) / denom; const intercept = (sumY - slope * sumX) / n; return { slope, intercept }; } function predictPowerLaw(model, nodes) { return Math.exp(model.intercept + model.slope * Math.log(nodes)); } const args = parseArgs(process.argv); const inputPath = args.get('input') || 'new-eval/b2c-auth-bench-output.txt'; const content = fs.readFileSync(inputPath, 'utf8'); const data = parseCsv(content); const targetNodes = Number(args.get('target') || 1_000_000); const grouped = new Map(); for (const row of data) { if (!grouped.has(row.scenario)) { grouped.set(row.scenario, []); } grouped.get(row.scenario).push(row); } const metrics = ['edges', 'buildMs', 'authMs', 'authQps', 'p95', 'p99']; console.log('b2c_auth_fit'); console.log(`target_nodes=${targetNodes}`); console.log('scenario,metric,model,predicted'); for (const [scenario, points] of grouped.entries()) { for (const metric of metrics) { const model = fitPowerLaw(points, metric); if (!model) continue; const predicted = predictPowerLaw(model, targetNodes); const modelLabel = `${Math.exp(model.intercept).toFixed(6)} * n^${model.slope.toFixed(3)}`; console.log([ scenario, metric, modelLabel, predicted.toFixed(3) ].join(',')); } }