Skip to content

Commit 136c39f

Browse files
committed
feat(web): add rank numbers to benchmark results display
- Display rank numbers (moltar#1, moltar#2, etc.) next to library names in charts - Calculate rankings based on average performance across selected benchmarks - Support ranking for all sort modes (fastest, alphabetical, popularity) - Improve readability for performance comparison presentations Closes moltar#2062
1 parent 19142f8 commit 136c39f

File tree

1 file changed

+62
-15
lines changed

1 file changed

+62
-15
lines changed

docs/src/App.tsx

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ function normalizePartialValues(values: BenchmarkResult[]): BenchmarkResult[] {
112112
normalized.push(...results);
113113

114114
const missingBenchmarks = BENCHMARKS.map(b => b.name).filter(
115-
n => !results.find(r => r.benchmark === n)
115+
n => !results.find(r => r.benchmark === n),
116116
);
117117

118118
missingBenchmarks.forEach(benchmark => {
@@ -208,7 +208,7 @@ async function graph({
208208
.filter(
209209
b =>
210210
selectedBenchmarkSet.has(b.benchmark) &&
211-
selectedNodeJsVersionsSet.has(b.runtimeVersion)
211+
selectedNodeJsVersionsSet.has(b.runtimeVersion),
212212
)
213213
.map(b => ({
214214
...b,
@@ -228,7 +228,7 @@ async function graph({
228228
.filter(
229229
b =>
230230
selectedBenchmarkSet.has(b.benchmark) &&
231-
selectedBunVersionsSet.has(b.runtimeVersion)
231+
selectedBunVersionsSet.has(b.runtimeVersion),
232232
)
233233
.map(b => ({
234234
...b,
@@ -239,7 +239,7 @@ async function graph({
239239
runtimesOrder.BUN,
240240
BENCHMARKS_ORDER[b.benchmark],
241241
BUN_VERSIONS.indexOf(
242-
getBunMajorAndMinorVersionNumber(b.runtimeVersion)
242+
getBunMajorAndMinorVersionNumber(b.runtimeVersion),
243243
),
244244
b.runtimeVersion,
245245
b.benchmark,
@@ -250,7 +250,7 @@ async function graph({
250250
.filter(
251251
b =>
252252
selectedBenchmarkSet.has(b.benchmark) &&
253-
selectedDenoVersionsSet.has(b.runtimeVersion)
253+
selectedDenoVersionsSet.has(b.runtimeVersion),
254254
)
255255
.map(b => ({
256256
...b,
@@ -298,11 +298,11 @@ async function graph({
298298

299299
if (sort === 'fastest' || !sort) {
300300
sortedValues = [...valuesNodejs, ...valuesBun, ...valuesDeno].sort(
301-
(a, b) => b.ops - a.ops
301+
(a, b) => b.ops - a.ops,
302302
);
303303
} else if (sort === 'alphabetically') {
304304
sortedValues = [...valuesNodejs, ...valuesBun, ...valuesDeno].sort(
305-
(a, b) => (a.name < b.name ? -1 : 1)
305+
(a, b) => (a.name < b.name ? -1 : 1),
306306
);
307307
} else if (sort === 'popularity') {
308308
sortedValues = [...valuesNodejs, ...valuesBun, ...valuesDeno].sort(
@@ -311,18 +311,65 @@ async function graph({
311311
const bPopularity = PACKAGES_POPULARITY[b.name] || 0;
312312

313313
return bPopularity - aPopularity;
314-
}
314+
},
315315
);
316316
}
317317

318318
// remove duplicates not sure whether vega-lite can handle that
319319
const sortedNames: string[] = [];
320+
const sortedNamesWithRank: string[] = [];
320321

321322
new Set(sortedValues.map(b => b.name)).forEach(n => sortedNames.push(n));
322323

324+
// Calculate average ops for ranking when multiple benchmarks are selected
325+
const rankingScores: { [name: string]: number } = {};
326+
327+
sortedNames.forEach(name => {
328+
const libraryResults = sortedValues.filter(v => v.name === name);
329+
if (libraryResults.length > 0) {
330+
const avgOps =
331+
libraryResults.reduce((sum, result) => sum + result.ops, 0) /
332+
libraryResults.length;
333+
rankingScores[name] = avgOps;
334+
}
335+
});
336+
337+
// Sort by ranking score and create names with rank numbers
338+
const rankedNames = sortedNames.sort((a, b) => {
339+
if (sort === 'fastest' || !sort) {
340+
return rankingScores[b] - rankingScores[a]; // Descending for fastest
341+
} else if (sort === 'alphabetically') {
342+
return a.localeCompare(b); // Alphabetical
343+
} else if (sort === 'popularity') {
344+
const aPopularity = PACKAGES_POPULARITY[a] || 0;
345+
const bPopularity = PACKAGES_POPULARITY[b] || 0;
346+
return bPopularity - aPopularity; // Descending for popularity
347+
}
348+
return 0;
349+
});
350+
351+
rankedNames.forEach((name, index) => {
352+
const rank = index + 1;
353+
const rankPrefix = `#${rank} `;
354+
sortedNamesWithRank.push(rankPrefix + name);
355+
});
356+
357+
// Update the values to include rank in the name for display
358+
const valuesWithRank = [...valuesNodejs, ...valuesBun, ...valuesDeno].map(
359+
value => {
360+
const rankIndex = rankedNames.indexOf(value.name);
361+
const rank = rankIndex + 1;
362+
const rankPrefix = `#${rank} `;
363+
return {
364+
...value,
365+
name: rankPrefix + value.name,
366+
};
367+
},
368+
);
369+
323370
const vegaSpec = vegaLite.compile({
324371
data: {
325-
values: [...valuesNodejs, ...valuesBun, ...valuesDeno],
372+
values: valuesWithRank,
326373
},
327374
height: {
328375
step: 15 / (nodeJsVersionCount + bunVersionCount + denoVersionCount),
@@ -339,7 +386,7 @@ async function graph({
339386
labelAlign: 'left',
340387
labelFontSize: 12,
341388
},
342-
sort: sortedNames,
389+
sort: sortedNamesWithRank,
343390
},
344391
},
345392
spec: {
@@ -526,7 +573,7 @@ export class App extends Component<
526573
this.setState({
527574
selectedBenchmarks: BENCHMARKS.reduce(
528575
(acc, b) => ({ ...acc, [b.name]: true }),
529-
{}
576+
{},
530577
),
531578
selectedNodeJsVersions: {},
532579
selectedBunVersions: {},
@@ -543,7 +590,7 @@ export class App extends Component<
543590
this.state.valuesNodeJs
544591
.map(v => v.runtimeVersion)
545592
.filter(v => v !== undefined)
546-
.sort((a, b) => (a < b ? 1 : -1))
593+
.sort((a, b) => (a < b ? 1 : -1)),
547594
);
548595
const res: string[] = [];
549596

@@ -557,7 +604,7 @@ export class App extends Component<
557604
this.state.valuesBun
558605
.map(v => v.runtimeVersion)
559606
.filter(v => v !== undefined)
560-
.sort((a, b) => (a < b ? 1 : -1))
607+
.sort((a, b) => (a < b ? 1 : -1)),
561608
);
562609
const res: string[] = [];
563610

@@ -571,7 +618,7 @@ export class App extends Component<
571618
this.state.valuesDeno
572619
.map(v => v.runtimeVersion)
573620
.filter(v => v !== undefined)
574-
.sort((a, b) => (a < b ? 1 : -1))
621+
.sort((a, b) => (a < b ? 1 : -1)),
575622
);
576623
const res: string[] = [];
577624

@@ -816,7 +863,7 @@ export class App extends Component<
816863

817864
<Graph
818865
benchmarks={BENCHMARKS.filter(
819-
b => this.state.selectedBenchmarks[b.name]
866+
b => this.state.selectedBenchmarks[b.name],
820867
)}
821868
nodeJsVersions={Object.entries(this.state.selectedNodeJsVersions)
822869
.sort()

0 commit comments

Comments
 (0)