Tracing is an effective way to narrow down points of interest when optimizing your app code.
Vega has built-in support for Perfetto which is a popular developer tool to record, analyze and visualize traces from App’s code.
This article provides step-by-step instructions for:
- Adding traces in an App’s JS code
- Record App traces
- Analyze App Traces in Perfetto UI
Add Traces in App code
Systrace is a React Native API to emit traces from App JS code and is supported in React Native for Vega.
Follow the below steps to add traces in your App’s JS code using the Systrace API.
Step 1: Identify the section of the code to trace
First, identify the section of the code you want to measure using tracing.
It is a good practice to add traces around the hottest parts of your code i.e. the ones that are executed most often or take the longest.
You can also work backwards from the performance issue you are investigating, and add traces around the code that is executed during the issue.
For example, if you are investigating a slow focus issue that surfaces when scrolling in a FlatList component that renders a TouchableOpacity component, you can add traces around the callback function passed to onFocus prop of the TouchableOpacity component.
Step 2: Add traces around the functions of interest
After you have identified the functions of interest, add traces around that function. Provide a unique and meaningful name in the traces that you can easily find later during analysis.
For example, for an onFocus issue in TouchableOpacity the tracing code would look something like this:
//Example Systrace code in KeplerVideoApp
import { Systrace } from "react-native";
const FocusableElement = ({
focusableElementRef,
children,
onPress,
onBlur,
onFocus,
getFocusState,
onFocusOverrideStyle,
style,
hasTVPreferredFocus,
...otherProps
}: FocusableElementProps) => {
const [isFocused, setIsFocused] = useState(false);
const focusHandler = () => {
Systrace.beginEvent("KeplerVideoApp:FocusedElement:onFocus"); // ---> Begin Trace
setIsFocused(true);
getFocusState?.(true);
onFocus?.();
Systrace.endEvent(); // ---> End Trace
};
const blurHandler = () => {
setIsFocused(false);
getFocusState?.(false);
onBlur?.();
};
return (
<TouchableOpacity
ref={focusableElementRef}
activeOpacity={1}
hasTVPreferredFocus={hasTVPreferredFocus}
onFocus={focusHandler}
onBlur={blurHandler}
onPress={onPress}
style={[style, isFocused ? onFocusOverrideStyle : undefined]}
testID={otherProps.testID}
{...otherProps}
>
{children}
</TouchableOpacity>
);
};
Record App Traces
After you have added the necessary traces in the App JS code, rebuild your App, run it on a Vega device, and record the traces.
Step 1: Rebuild Your App
Rebuild your App to ensure that the added traces are included in the App bundle.
A ‘Release’ build is recommended to accurately measure the trace durations.
Refer to Build Your App for steps.
Step 2: Install and Run your App
Install and run the version of the app built in the previous step to ensure the traces you added in the code are recorded.
It is recommended to run the app on a Vega device to accurately measure the trace durations.
Refer to Run Your App for steps.
Step 3: Record App Traces
To record the traces, do a recording of the scenario that has a performance issue, using the Activity Monitor Tool in Vega Studio IDE or CLI.
- Instructions for recording in Vega Studio IDE
- Instructions for recording from CLI
- Run the
perf record --app-name <<interactive-component-id>>command to record a trace - Run the
perf activity-monitor --app-name <<interactive-component-id>>if therecordcommand fails to work.
- Run the
For example, for a scrolling issue in onFocus handler within TouchableOpacity that is part of a FlatList, the recording steps would look something like this:
- Launch the App
- Run Activity Monitor
- Start Recording
- Perform Scrolling within the App
- Stop Recording
Once recording is complete, you should see the output files recorded by Activity Monitor in your project under the generated directory.
Activity Monitor creates one directory under
generatedper recording session. The name of the directory indicates the recording timestamp.
The generated directory for Activity Monitor contains the following files:
| FileName | Description |
|---|---|
| iter*trace*-converted.json | JS CPU Profiler trace file transformed for Vega Studio IDE |
| iter*trace*-original.json | JS CPU Profiler trace file compatible with Chrome Dev Tools |
| iter*_vs_trace | Perfetto Trace File |
| *trace-recorder.json | Trace file recorded by Activity Monitor. You can open this file using Recording View to inspect data collected by Activity Monitor |
Analyze App Traces in Perfetto UI
Step 1: Open trace file in Perfetto UI
After you have collected the traces, you can inspect them in Perfetto UI to analyze further and understand if the time taken between the trace points is expected.
Navigate to https://ui.perfetto.dev/ to access Perfetto UI, then click on “Open trace file” in the left menu and select the iter*_vs_trace file from the generated directory.
Alternately, you can also drag the iter*_vs_trace file from the generated directory directly onto the https://ui.perfetto.dev/ webpage.
Step 2: Analyze App traces
After the trace file loads in Perfetto, you can find the traces you added in the code using the search bar at the top by entering the trace name.
For example, a KeplerVideoApp:FocusedElement:onFocus trace added in the onFocus handler appears like this:

Once you locate the trace, analyze the duration of the trace across all occurrences and check if it’s expected. If there are traces stacked below a trace, see if the stack trace is expected.
Once you have identified traces that are taking longer than expected, you can use the Activity Monitor in Vega Studio to investigate CPU usage and hot functions during the same scenario. For broader performance best practices, refer to the App Performance Best Practices guide.
Last updated: Mar 10, 2026

