29 lines
1.8 KiB
JavaScript
29 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
const base = (process.argv[2] || process.env.ALT_URL || 'http://127.0.0.1:3000').replace(/\/$/,'');
|
|
const video = process.env.VIDEO_ID || 'dQw4w9WgXcQ';
|
|
const generation = process.env.MEDIA_GEN || '1';
|
|
const query = process.env.SEARCH_QUERY || 'worship';
|
|
const seconds = Number(process.env.BENCH_SECONDS || 3);
|
|
const scenarios = [
|
|
['version','/api/version',false], ['static-css','/styles.css',false],
|
|
['cached-search',`/api/search?q=${encodeURIComponent(query)}`,false],
|
|
['cached-range',`/api/media/${encodeURIComponent(video)}?g=${encodeURIComponent(generation)}`,true],
|
|
];
|
|
const percentile = (values,p) => values.length ? values[Math.min(values.length-1,Math.ceil(values.length*p)-1)] : 0;
|
|
async function run(path, range, concurrency) {
|
|
const latencies=[]; let bytes=0, count=0, failures=0; const until=Date.now()+seconds*1000;
|
|
await Promise.all(Array.from({length:concurrency},async()=>{
|
|
while(Date.now()<until) {
|
|
const start=performance.now();
|
|
try { const response=await fetch(base+path,{headers:range?{Range:'bytes=0-65535'}:{},signal:AbortSignal.timeout(30000)}); const data=await response.arrayBuffer(); bytes+=data.byteLength; count++; if(!response.ok)failures++; }
|
|
catch { failures++; }
|
|
latencies.push(performance.now()-start);
|
|
}
|
|
}));
|
|
latencies.sort((a,b)=>a-b); return {endpoint:path,concurrency,seconds,requests:count,requestsPerSecond:+(count/seconds).toFixed(2),bytes,latencyMs:{p50:+percentile(latencies,.5).toFixed(2),p95:+percentile(latencies,.95).toFixed(2)},failures};
|
|
}
|
|
for(const [name,path,range] of scenarios) for(const concurrency of [1,10,50,200]) {
|
|
try { console.log(JSON.stringify({name,...await run(path,range,concurrency)})); }
|
|
catch(e) { console.error(JSON.stringify({name,path,concurrency,error:String(e)})); process.exitCode=1; }
|
|
}
|