Skip to content

Commit 1eca581

Browse files
sammy-SCmeta-codesync[bot]
authored andcommitted
Add C++ sampling profiler support with FANTOM_PROFILE_CPP (#55735)
Summary: Pull Request resolved: #55735 changelog: [internal] Add support for profiling C++ code in Fantom tests using Linux `perf`. When `FANTOM_PROFILE_CPP=1` is set, the fantom_tester binary is wrapped with `perf record` to capture sampling profiler data with DWARF call graphs. Usage: ``` FANTOM_PROFILE_CPP=1 yarn fantom --benchmarks --testPathPattern="View-benchmark" ``` Output is saved to `.out/cpp-traces/perf-<timestamp>.data` and can be analyzed with: ``` perf report -i .out/cpp-traces/perf-<timestamp>.data ``` Reviewed By: rubennorte Differential Revision: D92155573 fbshipit-source-id: bde3ffcd11468e4ad88bec4b547726bed7cbde41
1 parent 2f9711d commit 1eca581

3 files changed

Lines changed: 59 additions & 3 deletions

File tree

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const VALID_ENVIRONMENT_VARIABLES = [
2121
'FANTOM_PRINT_OUTPUT',
2222
'FANTOM_DEBUG_JS',
2323
'FANTOM_PROFILE_JS',
24+
'FANTOM_PROFILE_CPP',
2425
'FANTOM_ENABLE_JS_MEMORY_INSTRUMENTATION',
2526
];
2627

@@ -70,6 +71,12 @@ export const debugJS: boolean = Boolean(process.env.FANTOM_DEBUG_JS);
7071

7172
export const profileJS: boolean = Boolean(process.env.FANTOM_PROFILE_JS);
7273

74+
/**
75+
* Enables C++ sampling profiler using Linux perf.
76+
* Saves perf.data files to .out/cpp-traces/ for analysis.
77+
*/
78+
export const profileCpp: boolean = Boolean(process.env.FANTOM_PROFILE_CPP);
79+
7380
/**
7481
* Enables address sanitizer (ASAN) build mode for the C++ side.
7582
*/

private/react-native-fantom/runner/executables/tester.js

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
import type {AsyncCommandResult, HermesVariant} from '../utils';
1212

13-
import {debugCpp, isCI} from '../EnvironmentOptions';
14-
import {NATIVE_BUILD_OUTPUT_PATH} from '../paths';
13+
import {debugCpp, isCI, profileCpp} from '../EnvironmentOptions';
14+
import {CPP_TRACES_OUTPUT_PATH, NATIVE_BUILD_OUTPUT_PATH} from '../paths';
1515
import {
1616
getBuckModesForPlatform,
1717
getBuckOptionsForHermes,
@@ -114,6 +114,10 @@ export function run(
114114
throw new Error('Cannot run Fantom with C++ debugging on CI');
115115
}
116116

117+
if (isCI && profileCpp) {
118+
throw new Error('Cannot run Fantom with C++ profiling on CI');
119+
}
120+
117121
if (!isCI && !debugCpp) {
118122
build(options);
119123
}
@@ -134,5 +138,46 @@ export function run(
134138
);
135139
}
136140

137-
return runCommand(getFantomTesterPath(options), args);
141+
const testerPath = getFantomTesterPath(options);
142+
143+
if (profileCpp) {
144+
// Ensure output directory exists
145+
if (!fs.existsSync(CPP_TRACES_OUTPUT_PATH)) {
146+
fs.mkdirSync(CPP_TRACES_OUTPUT_PATH, {recursive: true});
147+
}
148+
149+
// Generate unique output path for perf data
150+
const perfOutputPath = path.join(
151+
CPP_TRACES_OUTPUT_PATH,
152+
`perf-${Date.now()}.data`,
153+
);
154+
155+
// Wrap command with perf record
156+
// -g: enable call-graph (stack traces)
157+
// -F 997: sample at 997 Hz (prime number to avoid aliasing)
158+
// --call-graph dwarf: use DWARF for accurate stack traces
159+
const result = runCommand('perf', [
160+
'record',
161+
'-g',
162+
'-F',
163+
'997',
164+
'--call-graph',
165+
'dwarf',
166+
'-o',
167+
perfOutputPath,
168+
'--',
169+
testerPath,
170+
...args,
171+
]);
172+
173+
// Log the output path after the command starts
174+
console.log(
175+
`\n🔥 C++ sampling profiler recording to: ${perfOutputPath}\n` +
176+
` View with: perf report -i ${perfOutputPath}\n`,
177+
);
178+
179+
return result;
180+
}
181+
182+
return runCommand(testerPath, args);
138183
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export const JS_TRACES_OUTPUT_PATH: string = path.join(
2525
OUTPUT_PATH,
2626
'js-traces',
2727
);
28+
export const CPP_TRACES_OUTPUT_PATH: string = path.join(
29+
OUTPUT_PATH,
30+
'cpp-traces',
31+
);
2832
export const JS_HEAP_SNAPSHOTS_OUTPUT_PATH: string = path.join(
2933
OUTPUT_PATH,
3034
'js-heap-snapshots',

0 commit comments

Comments
 (0)