Vega App Performance with JS Traces and Perfetto

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:

  1. Adding traces in an App’s JS code
  2. Record App traces
  3. 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.

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:

  1. Launch the App
  2. Run Activity Monitor
  3. Start Recording
  4. Perform Scrolling within the App
  5. 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 generated per 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:

kva-onFocusTrace-perfetto

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