Skip to content

Commit 77ee24d

Browse files
rshestfacebook-github-bot
authored andcommitted
Print benchmark comparison results in a tabular format (#53097)
Summary: Pull Request resolved: #53097 # Changelog: [Internal] - This makes the benchmark results comparison printout, added in #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
1 parent 327057f commit 77ee24d

2 files changed

Lines changed: 80 additions & 22 deletions

File tree

private/react-native-fantom/runner/benchmarkUtils.js

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
* @format
99
*/
1010

11+
import {markdownTable} from './utils';
12+
1113
type TestTaskTiming = {
1214
name: string,
1315
latency: {
@@ -31,7 +33,7 @@ export const printBenchmarkResultsRanking = (
3133
testArtifact: mixed,
3234
}>,
3335
) => {
34-
const testTaskTimings: {[string]: Array<[string, number]>} = {};
36+
const testTaskTimings: {[string]: {[string]: number}} = {};
3537
let numTestVariants = 0;
3638

3739
for (const testResult of testResults) {
@@ -49,38 +51,33 @@ export const printBenchmarkResultsRanking = (
4951
for (const taskTiming of testArtifact.timings) {
5052
const taskName = taskTiming.name;
5153
if (testTaskTimings[taskName] === undefined) {
52-
testTaskTimings[taskName] = [];
54+
testTaskTimings[taskName] = {};
5355
}
54-
testTaskTimings[taskName].push([
55-
testResult.title,
56-
taskTiming.latency.p50,
57-
]);
56+
testTaskTimings[taskName][testResult.title] = taskTiming.latency.p50;
5857
}
5958
}
6059
if (numTestVariants <= 1 || Object.keys(testTaskTimings).length === 0) {
6160
// No benchmark results to print, or there is nothing to compare with
6261
return;
6362
}
6463

65-
// Sort by each task's execution times
64+
// Find relative execution times for tasks
65+
const results: {[string]: {[string]: string}} = {};
6666
for (const taskName in testTaskTimings) {
67-
testTaskTimings[taskName].sort((a, b) => a[1] - b[1]);
67+
const kv = Object.entries(testTaskTimings[taskName]);
68+
kv.sort((a, b) => a[1] - b[1]);
69+
const bestTiming = kv[0][1];
70+
results[taskName] = {};
71+
kv.forEach(([key, val]) => {
72+
results[taskName][key] =
73+
`${val.toFixed(3)}ms ${getTimingDelta(bestTiming, val)}`;
74+
});
75+
results[taskName][kv[0][0]] = `🏆 ${bestTiming.toFixed(3)}ms`;
6876
}
6977

70-
// Print the rankings
71-
console.log('### Benchmark Results Ranking ###');
72-
for (const taskName in testTaskTimings) {
73-
console.log(`> ${taskName}:`);
74-
let lastTiming;
75-
for (const [i, [testVariationName, latency]] of testTaskTimings[
76-
taskName
77-
].entries()) {
78-
console.log(
79-
` ${i + 1}. ${testVariationName}: ${latency.toFixed(2)}ms ${getTimingDelta(lastTiming, latency)}`,
80-
);
81-
lastTiming = latency;
82-
}
83-
}
78+
console.log('### Benchmark Times Comparison (p50): ###');
79+
console.log(markdownTable(results, 'Task name'));
80+
console.log('');
8481
};
8582

8683
function getTimingDelta(lastTiming: ?number, currentTiming: ?number): string {

private/react-native-fantom/runner/utils.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,64 @@ export function printConsoleLog(log: ConsoleLogMessage): void {
371371
break;
372372
}
373373
}
374+
375+
// Returns a markdown table corresponding to the given data, adopted from the RN console.table polyfill implementation
376+
export function markdownTable(
377+
data: {[string]: {[string]: string}},
378+
indexColumnName?: string = '',
379+
): string {
380+
const repeat = (element: string, n: number) =>
381+
Array.apply(null, Array(n)).map(() => element);
382+
383+
const rows = Object.keys(data).map((key: string) => ({
384+
[indexColumnName]: key,
385+
...data[key],
386+
}));
387+
388+
if (rows.length === 0) {
389+
return '';
390+
}
391+
392+
const columns = Array.from(
393+
rows.reduce((columnSet: Set<string>, row) => {
394+
Object.keys(row).forEach(key => columnSet.add(key));
395+
return columnSet;
396+
}, new Set()),
397+
);
398+
const stringRows: Array<Array<string>> = [];
399+
const columnWidths = [];
400+
401+
// Figure out max cell width for each column
402+
columns.forEach((k, i) => {
403+
columnWidths[i] = k.length;
404+
for (let j = 0; j < rows.length; j++) {
405+
const cellStr = rows[j][k];
406+
stringRows[j] = stringRows[j] || [];
407+
stringRows[j][i] = cellStr;
408+
columnWidths[i] = Math.max(columnWidths[i], cellStr.length);
409+
}
410+
});
411+
412+
// Join all elements in the row into a single string with | separators
413+
// (appends extra spaces to each cell to make separators | aligned)
414+
const joinRow = (row: Array<string>, space?: string = ' ') => {
415+
const cells = row.map((cell: string, i) => {
416+
const extraSpaces = repeat(' ', columnWidths[i] - cell.length).join('');
417+
return cell + extraSpaces;
418+
});
419+
return '| ' + cells.join(space + '|' + space) + ' |';
420+
};
421+
422+
const separators = columnWidths.map(columnWidth =>
423+
repeat('-', columnWidth).join(''),
424+
);
425+
const separatorRow = joinRow(separators);
426+
const header = joinRow(columns);
427+
const table = [header, separatorRow];
428+
429+
for (let i = 0; i < rows.length; i++) {
430+
table.push(joinRow(stringRows[i]));
431+
}
432+
433+
return '\n' + table.join('\n');
434+
}

0 commit comments

Comments
 (0)