mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
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:
1 parent
327057fad5
commit
77ee24ddce
2 files changed
+80
-22
No files matched your search
+19
-22
@@ -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
@@ -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');
|
||||
}
|
||||
Reference in new issue
Block a user