
When an Android app feels slow, stutters, or has choppy animations (disable system animations)There's almost always a hidden culprit lurking in the background: latency and the dreaded jank. Android offers several diagnostic tools, but one of the most powerful and flexible is perfetto, combined with the classic command dumpsys and data sources such as ftrace, atrace o heapprofdUnderstanding how to use them properly allows you to go from the vague feeling of "my app is acting strange" to having concrete numbers, traces, and causes.
In this article we will break down, calmly but directly, how does it work perfetto On Android, what usage modes does it have, what data sources can it activate, and how does it complement other key commands such as dumpsys gfxinfo, dumpsys meminfo o dumpsys batterystatsThe idea is to give you a complete overview of everything you can measure and how to use it to optimize latency, eliminate janks, and incidentally improve memory, network, and battery consumption.
What is Perfetto and why is it so useful for latency and jank?
perfetto It is a performance tracing tool integrated into Android. which is normally invoked from the computer using Android Debug Bridge (ADB) with commands like adb shell perfetto ...Its mission is to collect low-level information about what's happening on the device: kernel activities, user annotations, memory usage, process statistics, etc., all in a trace format that you can then analyze with viewers like the website of perfetto.dev.
Perfetto draws on several specialized “data sources”, among which stand:
ftrace, which captures kernel events (thread scheduling, file system, etc.).atrace, focused on annotations from the user space for services and applications.heapprofd, focused on sampling native memory usage in services and apps.
By combining these sources appropriatelyYou can record exactly the information you need to track UI latency issues, skipped frames, CPU spikes, or I/O-related locks. UFS storage.

Basic syntax of Perfetto and modes of operation
Perfetto can be used in two main modes: light and normalBoth are called from ADB, but they differ greatly in how they configure what is plotted and how it is saved.
The general idea is always the same: execute a command adb shell perfetto specifying duration, buffer size, data sources, and output trace file. The resulting file is typically generated following the protocol format. trace.proto from AOSP, which you can then open in Perfetto's analysis tools.
General options when invoking Perfetto
Regardless of the mode (light or normal)There are a number of common flags that control how the capture is executed, what is done with the generated file, and how it is integrated with alerting or remote upload systems:
--backgroundo-d: makesperfettoExit the command line interface and continue recording in the background.--background-waito-DSimilar to the previous one, but waits up to 30 seconds for all data sources to confirm they have started. The exit code will be 0 if everything is working correctly and anything other than 0 if there is an error or timeout.--alert-id,--config-id,--config-uidy--subscription-id: identifiers that link the trace to alerts or trigger configurations defined in the system, useful in automated monitoring scenarios.--out OUT_FILEo-o OUT_FILE: full path where the trace file will be saved, or-if you prefer that I go tostdoutA directory is generally used as/data/misc/perfetto-traces.--upload: upon completion of the capture, deliver the trace file to the packet specified by the messageIncidentReportConfigin the prototype configuration.--no-guardrailsy--reset-guardrails: They control the security mechanisms and resource limitations when automatic upload is activated (--upload), designed for testing and not so much for production.--rsave-for-bugreport: if the capture has abugreport_scoregreater than 0, saves the trace to a file and displays the path upon completion, for easy attachment to error reports.--queryy--query-rawThey query the status of the trace service. The first provides readable output, the second returns the protocoded content oftracing_service_state.proto.--helpo-h: Prints the tool's built-in help.
Perfetto's light mode: fast and similar to Systrace
Perfetto's light mode is designed for fast tracesvery similar to how it was used historically systraceIt allows you to select only a basic subset of sources: essentially atrace y ftraceand it's useful alongside apps to optimize performance.
Typical syntax in lightweight mode It's something like this:
adb shell perfetto ... --out FILE
Among the most relevant specific options of light mode we find:
--time TIMEo-t TIME: duration of the trace in seconds, minutes, or hours. For example,--time 1mCapture for one minute. If nothing is specified, 10 seconds are used by default.--buffer SIZEo-b SIZE: size of the circular buffer in memory. The default value is usually something like--buffer 32mb.--size SIZEo-s SIZE: Maximum file size limit on disk. If not configured, Perfetto can only write to the memory buffer.--appo-a: name of the Android app package to use in annotations ofatrace.
Following these flags are listed “event specifiers”which determine which categories or events will be recorded:
ATRACE_CAT: categories ofatracethat you want to enable (for example,wm(for WindowManager). A typical command would be:adb shell perfetto --out FILE wm.FTRACE_GROUP/FTRACE_NAME: specific events offtraceas thesched/sched_switchYou could run:adb shell perfetto --out FILE sched/sched_switch.
Perfetto's normal mode: maximum control and more sources
Perfetto's normal mode is much more powerful and configurableInstead of passing individual categories, you are given a configuration file (a proto) that describes in detail which data sources to activate, how to sample, which buffers to use, etc.
The usual syntax for normal mode is
adb shell perfetto --config CONFIG_FILE --out FILE
The specific flags that are key in this mode are:
--config CONFIG_FILEo-c CONFIG_FILE: path to the configuration file that follows the scheme oftrace_config.protoin AOSP. Within this prototype, elements such asTraceConfigyDataSourceConfig(defined indata_source_config.proto) to select and parameterize the data sources.--txt: indicates that the configuration file is in text formatpbtxtinstead of binary. Very convenient for local prototyping, but not recommended as a final production format.
Perfetto compatible data sources
Perfetto's true strength lies in the various resources it can enable.Each one is configured from the prototype through a block of DataSourceConfigAnd depending on the device, the Android version, and the kernel, you will have more or fewer options available.

Kernel events with ftrace
The fountain ftrace Perfetto allows you to capture internal kernel eventswhich is pure gold when you want to understand why a thread isn't scheduling on time or what's blocking the CPU at any given moment.
To activate ftrace from settings the field needs to be defined ftrace_config within DataSourceConfig...by selecting which specific events we want to track. Some common examples related to process scheduling are:
sched/sched_switchsched/sched_wakeupsched/sched_wakeup_newsched/sched_process_execsched/sched_process_exitsched/sched_process_forksched/sched_process_freesched/sched_process_hangsched/sched_process_wait
File system events and backtracking annotations can also be enabled.so that a single trace captures both kernel data and higher-level events. The list of actual events will always depend on the device and its kernel, so it's advisable to consult the relevant configuration protocols.
Process and system statistics
Another very practical source is that of process statistics and the system itself.It allows obtaining periodic counters of resource usage, both globally and per individual process, ideal for correlating CPU or memory spikes with specific jank events and with background apps.
To use it, you need to configure the fields. process_stats_config y sys_stats_config within DataSourceConfigThe data obtained includes, among other things, CPU time information, memory usage, and other metrics that may vary depending on the device and operating system version.
Native memory profiles with heapprofd
heapprofd It's the key piece when you need to understand the use of native memory of your application or system services. It works by sampling, generating profiles that indicate which parts of the code are reserving memory.
To light heapprofd in a trace of Perfetto You need to fill in the section heapprofd_config de DataSourceConfig. The result are ProfilePackets with call stack information, including Java frameworks when available. It's a powerful way to hunt for native leaks or inefficient allocation patterns.
Public documentation in perfetto.dev It delves into how to configure these profiles, filter by specific processes, adjust the sampling frequency, etc., allowing you to tailor the cost of the instrumentation to the level of detail you need.
Other additional data sources
In addition to the above, more sources are available depending on the device and Android version.Some are geared towards energy, others towards the network, or towards more specific framework metrics. To see them in detail, you need to review the different configuration schemes for Perfetto data sources published on AOSP.
In any case, the pattern always repeats itselfYou choose the source, you configure its block DataSourceConfig in the prototype of TraceConfig and you launch the trace with perfettoThen, you analyze the resulting file with the visualization tools.
dumpsys: the perfect plugin for measuring latency and performance
Although Perfetto is the star for low-level tracesthe veteran tool dumpsys It remains essential when you want high-level diagnostics, grouped by system service: input, graphics, network, battery, memory, etc.
dumpsys It runs on the Android device. and it is invoked from ADB with commands like adb shell dumpsysIf you run it without parameters, it dumps information from all system services, which is usually excessive. It's best to specify the particular service you're interested in to focus solely on that part.
General syntax of the dumpsys command
The generic way to call dumpsys is
adb shell dumpsys | -c | -h]
Some common uses are:
adb shell dumpsys: overturns all services (very verbose).adb shell dumpsys input: input system status (keyboards, touch screens, etc.).adb shell dumpsys -l: list all available services.
Among the main command-line options include:
-t timeout: maximum time in seconds given todumpsysto complete the operation (default, 10s).--help: generic tool help.-l: list of system services.--skip services: indicates one or more services that you want to exclude from the output when you do not specify any specific one.serviceSpecify the specific service you want to inspect, with optional arguments. If you're unsure, many services accept-hto show their own help, for exampleadb shell dumpsys procstats -h.-c: causes certain services to return data in a format more suitable for consumption by scripts or tools.-h: In some services, print specific additional help.
Input diagnostics: touches, keystrokes, and event latencies
For latency issues related to touch or keyboard inputThe key service is input. With adb shell dumpsys input You get a dump of the state of the input devices and the flow of events from when they are generated until they reach the windows.
The output includes three important logic blocks: the status of the Event Hub, the status of InputReader and the state of InputDispatcherEach one helps you detect flaws in a part of the event's journey.
Event Hub: Available devices and their configuration
The “Event Hub State” lists all input devices that the system knows about., with information such as the device path, class, keylayout files, keychars and configuration, as well as the built-in keyboard identifier (BuiltInKeyboardId).
When reviewing this section, it is advisable to check:
- That all expected physical devices are correctly listed.
- Each key has its own assigned key layout file, character map, and configuration file; if these are missing or contain syntax errors, they will not load, and the input experience will suffer.
- That the field
Classeshave the appropriate bits, mapped to constants likeINPUT_DEVICE_CLASS_TOUCH_MTenEventHub.h. - Which
BuiltInKeyboardIdis-2When there is no integrated keyboard, or match the internal keyboard ID otherwise. If you see that it is not-2And it should be; there's probably a missing special character map for some function keypad, which should only containtype SPECIAL_FUNCTION.
InputReader: How input events are interpreted
InputReader It is responsible for "translating" low-level kernel events to something the framework can understand: touch coordinates, pressure, touch size, etc. In its dump, you'll see the detailed configuration of each device (for example, a specific touchscreen) and the latest actions performed.
In the case of touchscreens, it is crucial to check:
- The X and Y ranges (minimums, maximums, precision, tolerances).
- The calibration parameters (size scales, pressure, orientation, etc.).
- The size of the surface (width and height in pixels).
- Translation and scaling factors, which determine how raw coordinates are mapped to screen space.
Global parameters are also listed at the end of this section. such as the tap interval, pointer speed thresholds, or gesture settings (double tap time, minimum distance, etc.), which directly affect the feeling of fluidity.
InputDispatcher: sending events to windows and ANR
InputDispatcher It handles the sending of incoming events to the different windowsIts status shows which window is in focus, which ones are touch-sensitive, the state of the input queues, and if there is an ANR (Application Not Responding) in progress.
In practice, this section allows you to check:
- Which window was receiving the taps at the time of the tap?
dumpsys. - If there are pending events or blocked queues that may be increasing perceived latency.
- How incoming connections are distributed among different windows and whether any are saturating their queue.
A simple but very revealing check It's just a touch of the screen, launch it immediately adb shell dumpsys input and see if the line of TouchStates Correctly identify the window you touched. If not, there's something wrong with the focus management or touch region mapping.
UI performance measurement with gfxinfo and framesstats
When the main concern is jank in animations and scrolling, the service gfxinfo He's your friend. Through dumpsys gfxinfo You can get data about the rendered frames for a specific app.
The basic command for a specific app is
adb shell dumpsys gfxinfo package-name
If you add the option framestatsThe diagnosis becomes even more detailed:
adb shell dumpsys gfxinfo package-name framestats
This will give you frame-by-frame latency statistics This data from recent animations is very helpful in identifying specific transitions or screens where rendering time spikes. This information can then be integrated into automated tests or macrobenchmarks to monitor for regressions between app versions.
Network diagnostics with dumpsys netstats
To understand if UI latency is related to slow network or traffic spikes, the service netstats It's very useful. It collects network usage statistics from the moment the device is turned on.
The typical command in more detail is
adb shell dumpsys netstats detail
The departure is organized into several sections.:
- Active interfaces and active UID interfaces, where names like
wlan0and its network identifier. - “Dev” and “Xt” statistics, which show historical data with time buckets (e.g., in one-hour increments) and fields such as bytes received (
rb), packages received (rp), bytes transmitted (tb), Etc. - Statistics by UID, where you can break down the network consumption of a specific app, differentiating between mobile and Wi-Fi.
To find your app's UIDSomething like this is used:
adb shell dumpsys package your-package-name | grep userId
Once you know the value of userId, you can look at the exit of netstats the lines with uid=ese_valor and see, for example, how many bytes and packets it has used in each two-hour period, and whether it was in the foreground (set=DEFAULT) or in the background (set=BACKGROUND).
Battery and energy usage with batterystats
Latency and jank are not only fixed with more performanceSometimes it's also worth looking at how optimizations affect energy consumption. dumpsys batterystats It provides a very comprehensive report on battery usage by UID and by component.
The base command for this service is
adb shell dumpsys batterystats options
If you want to focus on a specific app since the last uploadIt is used:
adb shell dumpsys batterystats --charged package-name
The usual departure includes:
- Battery-related event history.
- Global device statistics.
- Energy usage estimates by UID and by system components.
- Mobile network usage time per app and package.
- Global statistics of system and app UIDs.
Check-in format (CSV) for automated analysis
If you need to process battery data using scripts or external toolsYou can generate a "machine-friendly" output with:
adb shell dumpsys batterystats --checkin
This format presents each observation in a CSV line.with a section identifier that determines how to interpret the other fields. Some examples of sections are:
vers: check-in, parcel and platform versions.uid: UID – package name relationship.apk,pr,sr,vib,fgetc.: use of processes, sensors, vibrator, foreground time, synchronizations, jobs, etc.ntygn: network statistics (bytes and mobile/Wi-Fi packets, uptime, etc.).bt,dc,lvBattery data such as times, levels, and discharges.wfl,gwfl,gble: specific Wi-Fi and Bluetooth information, including times and estimated consumption in mAh.
In recent versions of Android (6.0 and up)The energy consumption of Wi-Fi, mobile radio, and Bluetooth is reported as elements pwi with dedicated labels (wifi, blue, cell), while in older versions it was grouped in the section m (miscellany).
Memory inspection over time with procstats
If you suspect the jank is coming from memory leaks or heavy apps running in the background, dumpsys procstats It allows you to see how your application behaves over time: how long it has been active, in what state, and with what memory consumption.
A typical use is to request statistics from the last few hours, For example:
adb shell dumpsys procstats --hours 3
The output summarizes for each app. The percentage of time the process has been alive, along with PSS, USS, and RSS values in the form of minimum, average, and maximum, along with the number of samples taken. It also shows a memory summary by process type (kernel, native, persistent, top, services, cached processes, etc.).
This aggregated view helps detect patterns such as applications that remain in background states for too long, or that maintain a very high average or maximum PSS, are potential candidates for optimization or may even be causing memory pressure that degrades system performance.
Detailed memory snapshot with meminfo
When you need a very granular snapshot of the memory usage of a specific processThe tool is dumpsys meminfoWith it you can see how RAM is distributed among native heaps, Dalvik/ART, code maps, graphics buffers, etc.
The basic syntax is:
adb shell dumpsys meminfo package_name|pid
The option -d More information for Dalvik/ARTshowing internal details such as the space for large objects (.LOS), GC overload, JIT cache, Zygote space, etc. With -h You can see all available flags.
The key columns to observe are usually Pss Total y Private DirtyThese figures reflect, respectively, the RAM usage adjusted by sharing and the amount of modified private memory that will be freed only upon process termination. Sometimes they are also of interest. Private Clean y Heap AllocIf you detect abnormal consumption, check how free up RAM to mitigate them.
Some relevant categories in the table:
Native HeapyDalvik Heap: native and VM heap memory usage.Heap AllocIt shows what the allocators believe is reserved, which may be higher than PSS due to the Zygote effect and shared memory..so mmap,.dex mmap,.oat mmapy.art mmap: RAM used by native code and bytecode, including ART images and their shared spaces..Heap,.LOS,.GC,.JITCache,.Zygote,.NonMoving,.IndirectRef(With-d): further break down the internal use of memory managed by ART.Unknown: pages that could not be classified into previous categories, often native assignments viewed through ASLR.
The TOTAL line groups the total PSS of the processwhich can be compared to the PSS of other processes and the available RAM. Private Dirty + Private Clean They indicate the memory that will be freed when the process is killed.
Additionally, high-level object counters are listed at the end of the report. as a number of ViewRootImpl, AppContexts o ActivitiesThis helps detect typical leaks of contexts or activities held by static references or by views/drawables that continue to point to them.
It is worth remembering one View or Drawable They also maintain reference to the Activity from which they originate, so improperly storing them can lead to leaks of all activity and its associated resources.
Combining Perfetto's detailed traces with dumpsys diagnostics (input, graphics, memory, network, and battery) provides a 360-degree view of how an Android app behaves: from when a thread is scheduled to how many milliseconds it takes to render a frame or how much excess memory and energy it consumes. Using these tools regularly in development and testing makes the difference between an app that "more or less works" and one that feels truly fluid, stable, and efficient, even on modest devices. optimize Android.
