import { createHash } from 'node:crypto'; import { arch, cpus, platform, release } from 'node:os'; const BENCHMARK_DATE = '2026-07-13'; const TRIALS = 100; const CLIENTS = 500; const WINDOW_MS = 100; const CAPACITY_PER_WINDOW = 25; const MAX_RETRIES = 8; const BASE_DELAY_MS = 250; const FIXED_DELAY_MS = 500; const MAX_DELAY_MS = 4000; class MinHeap { constructor(compare) { this.compare = compare; this.items = []; } get size() { return this.items.length; } push(value) { const items = this.items; items.push(value); let index = items.length - 1; while (index > 0) { const parent = Math.floor((index - 1) / 2); if (this.compare(items[parent], items[index]) <= 0) break; [items[parent], items[index]] = [items[index], items[parent]]; index = parent; } } pop() { if (this.items.length === 0) return null; const first = this.items[0]; const last = this.items.pop(); if (this.items.length > 0) { this.items[0] = last; let index = 0; while (true) { const left = index * 2 + 1; const right = left + 1; let smallest = index; if (left < this.items.length && this.compare(this.items[left], this.items[smallest]) < 0) { smallest = left; } if (right < this.items.length && this.compare(this.items[right], this.items[smallest]) < 0) { smallest = right; } if (smallest === index) break; [this.items[index], this.items[smallest]] = [this.items[smallest], this.items[index]]; index = smallest; } } return first; } } function seededRandom(seed) { let state = seed >>> 0; return () => { state = (state + 0x6D2B79F5) >>> 0; let value = state; value = Math.imul(value ^ (value >>> 15), value | 1); value ^= value + Math.imul(value ^ (value >>> 7), value | 61); return ((value ^ (value >>> 14)) >>> 0) / 4294967296; }; } function median(values) { if (values.length === 0) return null; const sorted = [...values].sort((left, right) => left - right); const middle = Math.floor(sorted.length / 2); return sorted.length % 2 === 0 ? (sorted[middle - 1] + sorted[middle]) / 2 : sorted[middle]; } function percentile(values, fraction) { if (values.length === 0) return null; const sorted = [...values].sort((left, right) => left - right); return sorted[Math.max(0, Math.ceil(sorted.length * fraction) - 1)]; } function exponentialDelay(retryNumber) { return Math.min(MAX_DELAY_MS, BASE_DELAY_MS * (2 ** (retryNumber - 1))); } const strategies = [ { id: 'immediate', label: 'Immediate retry', description: 'Retry after 1 millisecond, effectively remaining in the same service window.', delay: () => 1, }, { id: 'fixed', label: 'Fixed delay', description: `Retry every ${FIXED_DELAY_MS} milliseconds.`, delay: () => FIXED_DELAY_MS, }, { id: 'exponential', label: 'Exponential backoff', description: `Start at ${BASE_DELAY_MS} milliseconds, double each retry, and cap at ${MAX_DELAY_MS} milliseconds.`, delay: (retryNumber) => exponentialDelay(retryNumber), }, { id: 'full-jitter', label: 'Exponential backoff with full jitter', description: 'Choose a seeded delay from 0 through the current exponential cap, with a 1 millisecond simulation minimum.', delay: (retryNumber, random) => Math.max(1, Math.floor(random() * (exponentialDelay(retryNumber) + 1))), }, ]; function simulate(strategy, seed) { const random = seededRandom(seed); let sequence = 0; const events = new MinHeap((left, right) => left.time - right.time || left.sequence - right.sequence); for (let clientId = 0; clientId < CLIENTS; clientId += 1) { events.push({ time: 0, clientId, retryNumber: 0, sequence: sequence += 1 }); } const usedByWindow = new Map(); const attemptsByWindow = new Map(); const retryAttemptsByWindow = new Map(); const successTimes = []; let totalAttempts = 0; let rejectedAttempts = 0; let saturatedRetryAttempts = 0; let finalFailures = 0; while (events.size > 0) { const event = events.pop(); const window = Math.floor(event.time / WINDOW_MS); const used = usedByWindow.get(window) ?? 0; totalAttempts += 1; attemptsByWindow.set(window, (attemptsByWindow.get(window) ?? 0) + 1); if (event.retryNumber > 0) { retryAttemptsByWindow.set(window, (retryAttemptsByWindow.get(window) ?? 0) + 1); } if (used < CAPACITY_PER_WINDOW) { usedByWindow.set(window, used + 1); successTimes.push(event.time); continue; } rejectedAttempts += 1; if (event.retryNumber > 0) saturatedRetryAttempts += 1; if (event.retryNumber >= MAX_RETRIES) { finalFailures += 1; continue; } const nextRetryNumber = event.retryNumber + 1; const delay = strategy.delay(nextRetryNumber, random); events.push({ time: event.time + delay, clientId: event.clientId, retryNumber: nextRetryNumber, sequence: sequence += 1, }); } return { successful_clients: successTimes.length, final_failures: finalFailures, total_attempts: totalAttempts, rejected_attempts: rejectedAttempts, saturated_retry_attempts: saturatedRetryAttempts, peak_attempts_per_window: Math.max(...attemptsByWindow.values()), peak_retry_attempts_per_window: Math.max(...retryAttemptsByWindow.values()), median_success_time_ms: median(successTimes), p95_success_time_ms: percentile(successTimes, 0.95), last_success_time_ms: successTimes.length > 0 ? Math.max(...successTimes) : null, }; } function aggregate(strategy) { const trials = Array.from({ length: TRIALS }, (_, index) => simulate(strategy, index + 1)); const metricNames = Object.keys(trials[0]); const medians = {}; const ranges = {}; for (const metric of metricNames) { const values = trials.map((trial) => trial[metric]).filter((value) => value !== null); medians[metric] = median(values); ranges[metric] = { minimum: Math.min(...values), maximum: Math.max(...values) }; } return { id: strategy.id, label: strategy.label, description: strategy.description, medians, ranges, }; } const scenario = { clients: CLIENTS, service_window_ms: WINDOW_MS, capacity_per_window: CAPACITY_PER_WINDOW, maximum_retries: MAX_RETRIES, base_delay_ms: BASE_DELAY_MS, fixed_delay_ms: FIXED_DELAY_MS, maximum_delay_ms: MAX_DELAY_MS, trial_seeds: 'Integers 1 through 100, using Mulberry32', }; const cpu = cpus()[0]?.model ?? 'Unknown'; const report = { benchmark: 'retry-strategy-simulation', benchmark_version: '1.0.0', benchmark_date: BENCHMARK_DATE, scenario, scenario_sha256: createHash('sha256').update(JSON.stringify(scenario)).digest('hex'), method: { trials_per_strategy: TRIALS, event_order: 'Ascending simulated millisecond, then insertion sequence', service_model: 'Fixed aligned windows with independent capacity in each window', result_statistic: 'Median trial metric, with minimum and maximum retained', collision_definition: 'A retry arriving after capacity is exhausted in its service window', }, environment: { node: process.version, operating_system: `${platform()} ${release()} ${arch()}`, cpu, logical_cpus: cpus().length, }, strategies: strategies.map(aggregate), }; process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);