forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathBenchmark.js
More file actions
129 lines (108 loc) · 3.34 KB
/
Benchmark.js
File metadata and controls
129 lines (108 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import {getConstants} from './index';
import nullthrows from 'nullthrows';
import NativeCPUTime from 'react-native/src/private/specs/modules/NativeCPUTime';
import {
Bench,
type BenchOptions,
type FnOptions,
type TaskResult,
} from 'tinybench';
type SuiteOptions = $ReadOnly<{
...Pick<
BenchOptions,
'iterations' | 'time' | 'warmup' | 'warmupIterations' | 'warmupTime',
>,
disableOptimizedBuildCheck?: boolean,
}>;
type SuiteResults = Array<$ReadOnly<TaskResult>>;
interface SuiteAPI {
add(name: string, fn: () => void, options?: FnOptions): SuiteAPI;
verify(fn: (results: SuiteResults) => void): SuiteAPI;
}
export function suite(
suiteName: string,
suiteOptions?: ?SuiteOptions,
): SuiteAPI {
const tasks: Array<{
name: string,
fn: () => void,
options: FnOptions | void,
}> = [];
const verifyFns = [];
global.it(suiteName, () => {
if (tasks.length === 0) {
throw new Error('No benchmark tests defined');
}
const {isRunningFromCI} = getConstants();
// If we're running from CI and there's no verification function, there's
// no point in running the benchmark.
// We still run a single iteration of each test just to make sure that the
// logic in the benchmark doesn't break.
const isTestOnly = isRunningFromCI && verifyFns.length === 0;
const overriddenOptions: BenchOptions = isTestOnly
? {
warmupIterations: 1,
warmupTime: 0,
iterations: 1,
time: 0,
}
: {};
const {disableOptimizedBuildCheck, ...benchOptions} = suiteOptions ?? {};
const bench = new Bench({
...benchOptions,
...overriddenOptions,
name: suiteName,
throws: true,
now: () => NativeCPUTime.getCPUTimeNanos() / 1000000,
});
for (const task of tasks) {
bench.add(task.name, task.fn, task.options);
}
bench.runSync();
if (!isTestOnly) {
printBenchmarkResults(bench);
}
for (const verify of verifyFns) {
verify(bench.results);
}
if (!isTestOnly && !NativeCPUTime.hasAccurateCPUTimeNanosForBenchmarks()) {
throw new Error(
'`NativeCPUTime` module does not provide accurate CPU time information in this environment. Please run the benchmarks in an environment where it does.',
);
}
if (__DEV__ && disableOptimizedBuildCheck !== true) {
throw new Error('Benchmarks should not be run in development mode');
}
});
const suiteAPI = {
add(name: string, fn: () => void, options?: FnOptions): SuiteAPI {
tasks.push({name, fn, options});
return suiteAPI;
},
verify(fn: (results: SuiteResults) => void): SuiteAPI {
verifyFns.push(fn);
return suiteAPI;
},
};
return suiteAPI;
}
function printBenchmarkResults(bench: Bench) {
const longestTaskNameLength = bench.tasks.reduce(
(maxLength, task) => Math.max(maxLength, task.name.length),
0,
);
const separatorWidth = 121 + longestTaskNameLength - 'Task name'.length;
console.log('-'.repeat(separatorWidth));
console.log(bench.name);
console.table(nullthrows(bench.table()));
console.log('-'.repeat(separatorWidth) + '\n');
}