Skip to content

Commit b2da6a6

Browse files
add p90ms measurement
1 parent 455e097 commit b2da6a6

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

benchmarking/src/benchmarking.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import nodeTimesPromises from "node:timers/promises";
22
import nodeFsPromises from "node:fs/promises";
33
import nodePath from "node:path";
4+
import { getPercentile } from "./utils";
45

56
export type FetchBenchmark = {
67
callDurationsMs: number[];
78
averageMs: number;
9+
p90Ms: number;
810
};
911

1012
export type BenchmarkingResults = {
@@ -82,9 +84,12 @@ async function benchmarkFetch(url: string, options: BenchmarkFetchOptions): Prom
8284

8385
const averageMs = callDurationsMs.reduce((time, sum) => sum + time) / callDurationsMs.length;
8486

87+
const p90Ms = getPercentile(callDurationsMs, 90);
88+
8589
return {
8690
callDurationsMs,
8791
averageMs,
92+
p90Ms,
8893
};
8994
}
9095

benchmarking/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ console.log("\n\nSummary: ");
3333
const summary = benchmarkingResults.map(({ name, fetchBenchmark }) => ({
3434
name,
3535
"average fetch duration (ms)": Math.round(fetchBenchmark.averageMs),
36+
"90th percentile (ms)": Math.round(fetchBenchmark.p90Ms),
3637
}));
3738
console.table(summary);
3839

benchmarking/src/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,25 @@ export async function parallelRunWithSpinner<T>(
3737

3838
return results;
3939
}
40+
41+
/**
42+
* Gets a specific percentile for a given set of numbers
43+
*
44+
* @param data the data which percentile value needs to be computed
45+
* @param percentile the requested percentile (a number between 0 and 100)
46+
* @returns the computed percentile
47+
*/
48+
export function getPercentile(data: number[], percentile: number): number {
49+
if (Number.isNaN(percentile) || percentile < 0 || percentile > 100) {
50+
throw new Error(`A percentile needs to be between 0 and 100, found: ${percentile}`);
51+
}
52+
53+
data = data.sort((a, b) => a - b);
54+
55+
const rank = (percentile / 100) * (data.length - 1);
56+
57+
const rankInt = Math.floor(rank);
58+
const rankFract = rank - rankInt;
59+
60+
return Math.round(data[rankInt]! + rankFract * (data[rankInt + 1]! - data[rankInt]!));
61+
}

0 commit comments

Comments
 (0)