-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbench-overall-ev.js
More file actions
97 lines (86 loc) · 3.13 KB
/
bench-overall-ev.js
File metadata and controls
97 lines (86 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const native = require('./native/index.node');
const { solveOverallEv } = native;
const configs = [
{ label: '6D H17 peek', options: { deckCount: 6, hitOnSoft17: true, dealerPeeks: true } },
{ label: '6D S17 peek', options: { deckCount: 6, hitOnSoft17: false, dealerPeeks: true } },
{ label: '8D H17 peek', options: { deckCount: 8, hitOnSoft17: true, dealerPeeks: true } },
{ label: '2D H17 peek', options: { deckCount: 2, hitOnSoft17: true, dealerPeeks: true } },
{ label: '1D H17 peek', options: { deckCount: 1, hitOnSoft17: true, dealerPeeks: true } },
{ label: '6D H17 no-peek', options: { deckCount: 6, hitOnSoft17: true, dealerPeeks: false } },
{ label: '8D S17 no-peek', options: { deckCount: 8, hitOnSoft17: false, dealerPeeks: false } },
{
label: '6D H17 peek + dead',
options: {
deckCount: 6, hitOnSoft17: true, dealerPeeks: true,
deadCards: { '5': 4, '6': 3, '0': 8 },
},
},
{
label: '2D H17 peek + dead',
options: {
deckCount: 2, hitOnSoft17: true, dealerPeeks: true,
deadCards: { '5': 2, '0': 4 },
},
},
];
const WARMUP = 2;
const RUNS = 5;
async function bench() {
console.log(`Benchmarking solveOverallEv — ${WARMUP} warmup + ${RUNS} timed runs per config\n`);
const baselineEVs = {};
for (const { label, options } of configs) {
// Warmup
for (let i = 0; i < WARMUP; i++) {
await solveOverallEv(options);
}
// Timed runs
const times = [];
let ev;
for (let i = 0; i < RUNS; i++) {
const start = performance.now();
const result = await solveOverallEv(options);
const elapsed = performance.now() - start;
times.push(elapsed);
ev = result.ev;
}
const avg = times.reduce((a, b) => a + b, 0) / times.length;
const min = Math.min(...times);
baselineEVs[label] = ev;
console.log(
`${label.padEnd(25)} ` +
`avg=${avg.toFixed(1).padStart(7)}ms ` +
`min=${min.toFixed(1).padStart(7)}ms ` +
`EV=${ev.toFixed(15)}`
);
}
// If a baseline file exists, compare
try {
const fs = await import('fs');
const baselinePath = './bench-baseline.json';
if (fs.existsSync(baselinePath)) {
const baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf-8'));
console.log('\n--- EV Comparison vs Baseline ---');
let allMatch = true;
for (const [label, ev] of Object.entries(baselineEVs)) {
if (label in baseline) {
const diff = Math.abs(ev - baseline[label]);
const match = diff < 1e-15;
if (!match) allMatch = false;
console.log(
`${label.padEnd(25)} diff=${diff.toExponential(3)} ${match ? 'OK' : 'MISMATCH!'}`
);
}
}
console.log(allMatch ? '\nAll EVs match baseline.' : '\nWARNING: EV mismatch detected!');
} else {
// Save baseline
fs.writeFileSync(baselinePath, JSON.stringify(baselineEVs, null, 2));
console.log(`\nBaseline saved to ${baselinePath}`);
}
} catch (e) {
console.error('Baseline comparison error:', e.message);
}
}
bench().catch(console.error);