[compiler] Add simple walltime measurement (#32331)
Adds a new Timing logger event to the compiler which currently only records the walltime of running the compiler from the time the babel plugin's Program visitor enters to the time it exits. To enable, run the compiler with `ENABLE_REACT_COMPILER_TIMINGS=1 ...` or `export ENABLE_REACT_COMPILER_TIMINGS=1` to set it by default.
lauren committed
Feb 7, 2025 at 16:04 UTC
989b0cccc215e5c4692552b0cc01d23938dcf99b
2 files changed
+67
-30
compiler/packages/babel-plugin-react-compiler/src/Babel/BabelPlugin.ts
+63
-30
@@ -6,12 +6,15 @@
6
*/
7
8
import type * as BabelCore from '@babel/core';
9
-import {compileProgram, parsePluginOptions} from '../Entrypoint';
9
+import {compileProgram, Logger, parsePluginOptions} from '../Entrypoint';
10
import {
11
injectReanimatedFlag,
12
pipelineUsesReanimatedPlugin,
13
} from '../Entrypoint/Reanimated';
14
15
+const ENABLE_REACT_COMPILER_TIMINGS =
16
+ process.env['ENABLE_REACT_COMPILER_TIMINGS'] === '1';
17
+
18
/*
19
* The React Forget Babel Plugin
20
* @param {*} _babel
@@ -28,35 +31,65 @@ export default function BabelPluginReactCompiler(
31
* prior to B, if A does not have a Program visitor and B does, B will run first. We always
32
* want Forget to run true to source as possible.
33
*/
31
- Program(prog, pass): void {
32
- let opts = parsePluginOptions(pass.opts);
33
- const isDev =
34
- (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
35
- process.env['NODE_ENV'] === 'development';
36
- if (
37
- opts.enableReanimatedCheck === true &&
38
- pipelineUsesReanimatedPlugin(pass.file.opts.plugins)
39
- ) {
40
- opts = injectReanimatedFlag(opts);
41
- }
42
- if (
43
- opts.environment.enableResetCacheOnSourceFileChanges !== false &&
44
- isDev
45
- ) {
46
- opts = {
47
- ...opts,
48
- environment: {
49
- ...opts.environment,
50
- enableResetCacheOnSourceFileChanges: true,
51
- },
52
- };
53
- }
54
- compileProgram(prog, {
55
- opts,
56
- filename: pass.filename ?? null,
57
- comments: pass.file.ast.comments ?? [],
58
- code: pass.file.code,
59
- });
34
+ Program: {
35
+ enter(prog, pass): void {
36
+ const filename = pass.filename ?? 'unknown';
37
+ if (ENABLE_REACT_COMPILER_TIMINGS === true) {
38
+ performance.mark(`${filename}:start`, {
39
+ detail: 'BabelPlugin:Program:start',
40
+ });
41
+ }
42
+ let opts = parsePluginOptions(pass.opts);
43
+ const isDev =
44
+ (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
45
+ process.env['NODE_ENV'] === 'development';
46
+ if (
47
+ opts.enableReanimatedCheck === true &&
48
+ pipelineUsesReanimatedPlugin(pass.file.opts.plugins)
49
+ ) {
50
+ opts = injectReanimatedFlag(opts);
51
+ }
52
+ if (
53
+ opts.environment.enableResetCacheOnSourceFileChanges !== false &&
54
+ isDev
55
+ ) {
56
+ opts = {
57
+ ...opts,
58
+ environment: {
59
+ ...opts.environment,
60
+ enableResetCacheOnSourceFileChanges: true,
61
+ },
62
+ };
63
+ }
64
+ compileProgram(prog, {
65
+ opts,
66
+ filename: pass.filename ?? null,
67
+ comments: pass.file.ast.comments ?? [],
68
+ code: pass.file.code,
69
+ });
70
+ if (ENABLE_REACT_COMPILER_TIMINGS === true) {
71
+ performance.mark(`${filename}:end`, {
72
+ detail: 'BabelPlugin:Program:end',
73
+ });
74
+ }
75
+ },
76
+ exit(_, pass): void {
77
+ if (ENABLE_REACT_COMPILER_TIMINGS === true) {
78
+ const filename = pass.filename ?? 'unknown';
79
+ const measurement = performance.measure(filename, {
80
+ start: `${filename}:start`,
81
+ end: `${filename}:end`,
82
+ detail: 'BabelPlugin:Program',
83
+ });
84
+ if ('logger' in pass.opts && pass.opts.logger != null) {
85
+ const logger: Logger = pass.opts.logger as Logger;
86
+ logger.logEvent(filename, {
87
+ kind: 'Timing',
88
+ measurement,
89
+ });
90
+ }
91
+ }
92
+ },
93
},
94
},
95
};
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts
+4
@@ -206,6 +206,10 @@ export type LoggerEvent =
206
kind: 'PipelineError';
207
fnLoc: t.SourceLocation | null;
208
data: string;
209
+ }
210
+ | {
211
+ kind: 'Timing';
212
+ measurement: PerformanceMeasure;
213
};
214
215
export type Logger = {