androidengineers.Book a session

Performance Optimization

Systrace & Perf Profiling

article20 minHard

Systrace (now superseded by Perfetto) gives you a system-wide timeline: every thread, every Binder call, every scheduled process — not just your app's activity. When frame drops don't appear in your code, the system trace reveals the real culprit.

Systrace vs Perfetto vs Android Profiler

ToolScopeBest for
Android Studio ProfilerApp onlyMethod-level flamecharts, heap dumps
Systrace (legacy)System + appCross-process, scheduling, Binder calls
Perfetto (modern)System + appSame as systrace; long traces; recommended

Always start with the Android Studio Profiler — it's fastest. Escalate to Perfetto when the bottleneck isn't visible in your code (scheduling delays, Binder latency, Zygote timing).

Adding Custom Trace Events

Instrument your code to appear in the trace timeline:

// Kotlin — wrap any block you want measured
import android.os.Trace

fun loadArticles() {
    Trace.beginSection("ArticleRepository.load")
    try {
        // ... expensive work
    } finally {
        Trace.endSection()
    }
}

// Or use the AndroidX tracing library for a cleaner API:
// implementation("androidx.tracing:tracing:1.1.0")
import androidx.tracing.trace

fun processArticles(articles: List<Article>) {
    trace("processArticles") {
        articles.forEach { processArticle(it) }
    }
}

Custom sections appear as colored slices in the Perfetto timeline under your app's thread.

Capturing a Perfetto Trace

# 1. Force-stop your app
adb shell am force-stop com.example.myapp

# 2. Start recording (10 second window)
adb shell perfetto \
  -c - --txt -o /data/misc/perfetto-traces/trace.pftrace \
<<EOF
buffers: { size_kb: 32768 }
data_sources: { config { name: "linux.ftrace"
    ftrace_config {
        ftrace_events: "sched/sched_switch"
        ftrace_events: "power/suspend_resume"
        atrace_categories: "view"
        atrace_categories: "gfx"
        atrace_categories: "am"
        atrace_apps: "com.example.myapp"
    }
} }
duration_ms: 10000
EOF

# 3. Launch your app and perform the scenario
adb shell am start-activity -n com.example.myapp/.MainActivity

# 4. Pull the trace
adb pull /data/misc/perfetto-traces/trace.pftrace ~/Desktop/

Open at ui.perfetto.dev.

Reading the Perfetto Timeline

Key rows to examine:

RowWhat it shows
com.example.myappYour app's CPU slices — when it ran
RenderThreadGPU draw calls; long slices = GPU bottleneck
Binder slicesCross-process calls; long = IPC bottleneck
Choreographer#doFrameFrame timing; should complete < 16ms
ActivityThread.mainYour main thread — look for long slices
Custom sectionsYour Trace.beginSection calls appear here

Identifying Scheduling Problems

If your frame looks fast in isolation but still jank on device, check:

  1. CPU frequency scaling: The trace shows CPU clock speed per core. If your main thread was scheduled on a power-efficiency core at half speed, it looks slow even when the code is fast.

  2. Preemption: Your thread may have been preempted (another process got the CPU). Look for gaps in your thread's timeline where the CPU was used by another process.

  3. Lock contention: Long waits on Monitor.notify suggest lock contention between threads.

Android Studio Method Tracer

For method-level detail without full systrace overhead:

// Programmatic sampling profiler
import android.os.Debug

override fun onResume() {
    Debug.startMethodTracingSampling("my_trace", 8_000_000, 1000)
}

override fun onPause() {
    Debug.stopMethodTracing()
    // Output: /sdcard/my_trace.trace
    // Open in Android Studio: Run → Open Trace Files
}

Key Takeaways

ScenarioTool
Method-level flame chartAndroid Studio CPU Profiler
Cross-process (Binder) analysisPerfetto
Startup timingPerfetto with android.startupapp data source
Scheduling delaysPerfetto with sched/sched_switch ftrace events
Custom section timingTrace.beginSection / trace { }

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Systrace & Perf Profiling | Android System Design | Android Engineers