Add performance regression detection: indexes, timing middleware, benchmark script

Nightshift-Task: perf-regression
Nightshift-Ref: https://github.com/marcus/nightshift
This commit is contained in:
2026-03-20 02:44:57 -04:00
parent ccd0fb2155
commit 0a1e3666ef
5 changed files with 94 additions and 1 deletions

62
scripts/perf-benchmark.js Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env node
'use strict';
const BASE_URL = process.env.BENCHMARK_URL || 'http://localhost:3001';
const ITERATIONS = 5;
const MEAN_THRESHOLD_MS = parseInt(process.env.SLOW_THRESHOLD_MS || '500', 10);
const ENDPOINTS = [
{ label: 'GET /api/paychecks', path: `/api/paychecks?year=${new Date().getFullYear()}&month=${new Date().getMonth() + 1}` },
{ label: 'GET /api/financing', path: '/api/financing' },
{ label: 'GET /api/summary/annual', path: `/api/summary/annual?year=${new Date().getFullYear()}` },
];
async function measureEndpoint(endpoint) {
const times = [];
for (let i = 0; i < ITERATIONS; i++) {
const start = Date.now();
const res = await fetch(`${BASE_URL}${endpoint.path}`);
const duration = Date.now() - start;
if (!res.ok) {
console.warn(` [warn] ${endpoint.label} returned HTTP ${res.status}`);
}
times.push(duration);
}
const min = Math.min(...times);
const max = Math.max(...times);
const mean = Math.round(times.reduce((a, b) => a + b, 0) / times.length);
return { min, mean, max };
}
(async () => {
console.log(`Benchmarking ${BASE_URL} (${ITERATIONS} iterations each, threshold ${MEAN_THRESHOLD_MS}ms)\n`);
let failed = false;
for (const endpoint of ENDPOINTS) {
let stats;
try {
stats = await measureEndpoint(endpoint);
} catch (err) {
console.error(` [error] ${endpoint.label}: ${err.message}`);
failed = true;
continue;
}
const flag = stats.mean >= MEAN_THRESHOLD_MS ? ' *** SLOW ***' : '';
console.log(`${endpoint.label}`);
console.log(` min=${stats.min}ms mean=${stats.mean}ms max=${stats.max}ms${flag}`);
if (stats.mean >= MEAN_THRESHOLD_MS) {
failed = true;
}
}
console.log('');
if (failed) {
console.error('FAIL: one or more endpoints exceeded the threshold or errored.');
process.exit(1);
} else {
console.log('PASS: all endpoints within threshold.');
}
})();