Print benchmark comparison results in a tabular format (#53097)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/53097

# Changelog:
[Internal] -

This makes the benchmark results comparison printout, added in https://github.com/facebook/react-native/pull/52925, be done in a tabular form, so it's easier to read and copy/paste around.

Reviewed By: lenaic

Differential Revision: D79728695

fbshipit-source-id: 4dfc999ad4a9a8c2d67efdfce11aff75383cf645
This commit is contained in:
Ruslan Shestopalyuk authored and Facebook GitHub Bot committed 2025-08-07 08:11:32 -07:00
1 parent 327057fad5
commit 77ee24ddce
2 files changed
+80 -22

No files matched your search

+19 -22
View File
@@ -8,6 +8,8 @@
* @format
*/
import {markdownTable} from './utils';
type TestTaskTiming = {
name: string,
latency: {
@@ -31,7 +33,7 @@ export const printBenchmarkResultsRanking = (
testArtifact: mixed,
}>,
) => {
const testTaskTimings: {[string]: Array<[string, number]>} = {};
const testTaskTimings: {[string]: {[string]: number}} = {};
let numTestVariants = 0;
for (const testResult of testResults) {
@@ -49,12 +51,9 @@ export const printBenchmarkResultsRanking = (
for (const taskTiming of testArtifact.timings) {
const taskName = taskTiming.name;
if (testTaskTimings[taskName] === undefined) {
testTaskTimings[taskName] = [];
testTaskTimings[taskName] = {};
}
testTaskTimings[taskName].push([
testResult.title,
taskTiming.latency.p50,
]);
testTaskTimings[taskName][testResult.title] = taskTiming.latency.p50;
}
}
if (numTestVariants <= 1 || Object.keys(testTaskTimings).length === 0) {
@@ -62,25 +61,23 @@ export const printBenchmarkResultsRanking = (
return;
}
// Sort by each task's execution times
// Find relative execution times for tasks
const results: {[string]: {[string]: string}} = {};
for (const taskName in testTaskTimings) {
testTaskTimings[taskName].sort((a, b) => a[1] - b[1]);
const kv = Object.entries(testTaskTimings[taskName]);
kv.sort((a, b) => a[1] - b[1]);
const bestTiming = kv[0][1];
results[taskName] = {};
kv.forEach(([key, val]) => {
results[taskName][key] =
`${val.toFixed(3)}ms ${getTimingDelta(bestTiming, val)}`;
});
results[taskName][kv[0][0]] = `🏆 ${bestTiming.toFixed(3)}ms`;
}
// Print the rankings
console.log('### Benchmark Results Ranking ###');
for (const taskName in testTaskTimings) {
console.log(`> ${taskName}:`);
let lastTiming;
for (const [i, [testVariationName, latency]] of testTaskTimings[
taskName
].entries()) {
console.log(
` ${i + 1}. ${testVariationName}: ${latency.toFixed(2)}ms ${getTimingDelta(lastTiming, latency)}`,
);
lastTiming = latency;
}
}
console.log('### Benchmark Times Comparison (p50): ###');
console.log(markdownTable(results, 'Task name'));
console.log('');
};
function getTimingDelta(lastTiming: ?number, currentTiming: ?number): string {
+61
View File
@@ -371,3 +371,64 @@ export function printConsoleLog(log: ConsoleLogMessage): void {
break;
}
}
// Returns a markdown table corresponding to the given data, adopted from the RN console.table polyfill implementation
export function markdownTable(
data: {[string]: {[string]: string}},
indexColumnName?: string = '',
): string {
const repeat = (element: string, n: number) =>
Array.apply(null, Array(n)).map(() => element);
const rows = Object.keys(data).map((key: string) => ({
[indexColumnName]: key,
...data[key],
}));
if (rows.length === 0) {
return '';
}
const columns = Array.from(
rows.reduce((columnSet: Set<string>, row) => {
Object.keys(row).forEach(key => columnSet.add(key));
return columnSet;
}, new Set()),
);
const stringRows: Array<Array<string>> = [];
const columnWidths = [];
// Figure out max cell width for each column
columns.forEach((k, i) => {
columnWidths[i] = k.length;
for (let j = 0; j < rows.length; j++) {
const cellStr = rows[j][k];
stringRows[j] = stringRows[j] || [];
stringRows[j][i] = cellStr;
columnWidths[i] = Math.max(columnWidths[i], cellStr.length);
}
});
// Join all elements in the row into a single string with | separators
// (appends extra spaces to each cell to make separators | aligned)
const joinRow = (row: Array<string>, space?: string = ' ') => {
const cells = row.map((cell: string, i) => {
const extraSpaces = repeat(' ', columnWidths[i] - cell.length).join('');
return cell + extraSpaces;
});
return '| ' + cells.join(space + '|' + space) + ' |';
};
const separators = columnWidths.map(columnWidth =>
repeat('-', columnWidth).join(''),
);
const separatorRow = joinRow(separators);
const header = joinRow(columns);
const table = [header, separatorRow];
for (let i = 0; i < rows.length; i++) {
table.push(joinRow(stringRows[i]));
}
return '\n' + table.join('\n');
}