mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-09-16 10:32:10 +00:00
test(performance): add a local pokédex benchmark and run it in CI
Measures the pokédex load against a local Supabase with a generated fixture, and compares runs so a regression shows up as a number rather than a hunch. Wired into test:ci and given its own job so the artifacts survive a failure.
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
const data = JSON.parse(await readFile(process.argv[2], 'utf8'));
|
||||
const warm = data.results.filter((row) => row.run === 'warm');
|
||||
const p75 = (values) => [...values].sort((a, b) => a - b)[Math.ceil(values.length * 0.75) - 1];
|
||||
const groups = [...new Set(warm.map((row) => `${row.fixture}/${row.navigation}`))];
|
||||
const paired = groups.map((group) => {
|
||||
const rows = (host) =>
|
||||
warm.filter((row) => `${row.fixture}/${row.navigation}` === group && row.host === host);
|
||||
for (const host of ['netlify', 'cloudflare'])
|
||||
if (rows(host).length < 30) throw new Error(`Insufficient ${host} warm samples for ${group}`);
|
||||
return {
|
||||
group,
|
||||
netlify: p75(rows('netlify').map((row) => row.interactiveMs)),
|
||||
cloudflare: p75(rows('cloudflare').map((row) => row.interactiveMs))
|
||||
};
|
||||
});
|
||||
if (groups.length !== 4)
|
||||
throw new Error(
|
||||
'Expected national and scoped-form fixtures, each with direct and client navigation'
|
||||
);
|
||||
const netlify = p75(warm.filter((row) => row.host === 'netlify').map((row) => row.interactiveMs));
|
||||
const cloudflare = p75(
|
||||
warm.filter((row) => row.host === 'cloudflare').map((row) => row.interactiveMs)
|
||||
);
|
||||
const improvement = netlify - cloudflare;
|
||||
const passes =
|
||||
improvement >= 200 &&
|
||||
improvement / netlify >= 0.2 &&
|
||||
paired.every((row) => row.cloudflare <= row.netlify * 1.1);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
overallP75: { netlify, cloudflare },
|
||||
improvementMs: improvement,
|
||||
improvementPercent: (100 * improvement) / netlify,
|
||||
groups: paired,
|
||||
performanceGatePassed: passes,
|
||||
recommendation:
|
||||
passes && data.compatibilityPassed && data.environment === 'deployed'
|
||||
? 'Cloudflare qualifies for a migration proposal; review operating cost before cutover.'
|
||||
: 'Retain Netlify: performance, deployed evidence or compatibility gate is unmet.'
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user