skip to content
Andrei Calazans

Bridging Trace API on Android

/ 2 min read

Last Updated:

In the previous post: Perfetto To Analyze App Start Performance…, we went over how to use Perfetto to visualize Systrace calls.

Now you might be wondering what else we can do with this? Below I’ll cover how you can use use Android’s Trace API.

Android’s Trace API

import androidx.tracing.Trace
...
Trace.beginSection("section_name")
...// Your code block to be traced
Trace.endSection()

The above will show up in Perfetto as a trace event, allowing you to see how long a specific section of your code takes to execute and correlate it with other events in your app.

Use Trace for:

  • Measuring UI performance (e.g., screen transitions)
  • Tracking execution of specific blocks during startup
  • Debugging jank or slow operations

The Trace API is not bridged by default in React Native. The internal React Native Systrace API is only available in DEV and isn’t properly setup for open source.

So we are left with having to bridge this ourselves for our Android trace analysis.

Trace Native Module

nit not using TurboModule on purpose for simplicity, here is a post with this module converted to TurboModule

In android/app/src/main/java/com/myrnapp/TracingModule.kt:

package com.myrnapp

import androidx.tracing.Trace
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod

class TracingModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    override fun getName(): String {
        return "TracingModule"
    }

    @ReactMethod
    fun beginSection(sectionName: String) {
        Trace.beginSection(sectionName)
    }

    @ReactMethod
    fun endSection() {
        Trace.endSection()
    }
}

Create a new file: android/app/src/main/java/com/myrnapp/TracingPackage.kt:

package com.myrnapp

import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager

class TracingPackage : ReactPackage {

    override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
        return listOf(TracingModule(reactContext))
    }

    override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
        return emptyList()
    }
}

In android/app/src/main/java/com/myrnapp/MainApplication.kt, inside getPackages():

override fun getPackages(): List<ReactPackage> =
    PackageList(this).packages.apply {
        // Add the tracing package manually
        add(TracingPackage())
    }

JS/TS usage:


function beginTraceSection(title: string) {
  if (Platform.OS === 'android') {
    NativeModules.TracingModule.beginSection(title);
  }
}

function endTraceSection() {
  if (Platform.OS === 'android') {
    NativeModules.TracingModule.endSection();
  }
}

beginTraceSection('render-app-tsx');
/* in some View's onLayout you can do:

<View
  onLayout={() => {
    endTraceSection();
  }}

*/

Done, now you can correlate your trace calls with the rest of the traces.

Trace logs in Perfetto