Profiling memory usage and allocations with Perfetto
In this guide, you'll learn how to:
- Understand the different memory profiling modes and when to use them.
- Record native and ART (Java/Kotlin) heap profiles with Perfetto.
- Visualize and analyze allocation profiles in the Perfetto UI.
The memory use of a process plays a key role in the performance of processes and impact on overall system stability. Understanding where and how your process is using memory can give significant insight to understand why your process may be running slower than you expect or just help make your program more efficient.
When it comes to apps and memory, there are mainly two ways a process can use memory:
Native C/C++/Rust code: typically allocate memory via libc's malloc/free (or wrappers on top of it like C++'s new/delete). Note that native allocations are still possible (and quite frequent) when using Java APIs that are backed by JNI counterparts. A canonical example is
java.util.regex.Patternwhich typically owns both managed memory on the Java heap and native memory due to the underlying use of native regex libraries.Java/KT code: a good portion of the memory footprint of an app lives in the managed heap (in the case of Android, managed by ART's garbage collector). This is where every
new X()object lives.
Perfetto offers multiple complementary techniques for debugging the above:
| Tool | Language | What is instrumented | Usage |
|---|---|---|---|
| ART Heap Dumps | Java/Kotlin | Reference graph of all allocated objects | Breakdown memory usage, and find leaks. |
| Native Allocation Profiling | Native C/C++/Rust | malloc + free |
Reduce native allocation churn, breakdown memory usage and find leaks after profiling started. |
| ART Allocation Profiling | Java/Kotlin | Object allocations | Reduce Java/Kotlin allocation churn |
Native (C/C++/Rust) Allocation Profiling (aka native heap profiling)
Native languages like C/C++/Rust commonly allocate and deallocate memory at the
lowest level by using the libc family of malloc/free functions. Native heap
profiling works by intercepting calls to these functions and injecting code
which keeps track of the callstack of memory allocated but not freed. This
allows to keep track of the "code origin" of each allocation. malloc/free can be
perf-hotspots in heap-heavy processes: in order to mitigate the overhead of the
memory profiler we support sampling to
trade-off accuracy and overhead.
NOTE: native heap profiling with Perfetto only works on Android and Linux; this is due to the techniques we use to intercept malloc and free only working on these operating systems.
A very important point to note is that heap profiling is not retroactive. It can only report allocations that happen after tracing has started. It cannot provide any insight into allocations that occurred before the trace began. If you need to analyze memory usage from the start of a process, you must begin tracing before the process is launched.
If your question is "why is this process so big right now?" you cannot use heap profiling to answer questions about what happened in the past. However our anecdotal experience is that if you are chasing a memory leak, there is a good chance that the leak will keep happening over time and hence you will be able to see future increments.
Collecting your first Native Allocation Profile
On Android Perfetto heap profiling hooks are seamlessly integrated into the libc implementation.
Prerequisites
- A device running Android 10+.
- A Profileable or Debuggable app. If you are running on a "user" build of Android (as opposed to "userdebug" or "eng"), your app needs to be marked as profileable or debuggable in its manifest. See the heapprofd documentation for more details.
Instructions
- Open https://ui.perfetto.dev/#!/record
- Select Android as target device and use one of the available transports. If in doubt, WebUSB is the easiest choice.
- Click on the
Memoryprobe on the left and then toggle theNative heap profilingoption. - Enter the process name in the
Namesbox. - The process name you have to enter is (the first argument of the) the process
cmdline. That is the right-most column (NAME) of
adb shell ps -A. - Select an observation time in the
Buffers and durationpage. This will determine for how long the profile will intercept malloc/free calls. - Press the red button to start recording the trace.
- While the trace is being recorded, interact with the process being profiled. Run your user journey, test patterns, interact with your app.

On Android Perfetto native heap profiling hooks are seamlessly integrated into the libc implementation.
Prerequisites
- ADB installed.
- Windows users: Make sure that the downloaded adb.exe is in the PATH.
set PATH=%PATH%;%USERPROFILE%\Downloads\platform-tools - A device running Android 10+.
- A Profileable or Debuggable app. If you are running on a "user" build of Android (as opposed to "userdebug" or "eng"), your app needs to be marked as profileable or debuggable in its manifest. See the heapprofd documentation for more details.
Instructions
$ adb devices -l
List of devices attached
24121FDH20006S device usb:2-2.4.2 product:panther model:Pixel_7 device:panther transport_id:1If more than one device or emulator is reported you must select one upfront as follows:
export ANDROID_SERIAL=24121FDH20006SDownload the tools/heap_profile (if you don't have a perfetto checkout):
curl -LO https://raw.githubusercontent.com/google/perfetto/main/tools/heap_profileThen start the profile using the android subcommand:
python3 heap_profile android -n com.google.android.apps.nexuslauncherThe bare invocation (python3 heap_profile -n ...) still works and is
equivalent to the android subcommand - it is kept for backwards
compatibility. New scripts should use the explicit subcommand form.
Run your test patterns, interact with the process and press Ctrl-C when done
(or pass -d 10000 for a time-limited profiling)
When you press Ctrl-C the heap_profile script will pull the traces and store them in /tmp/heap_profile-latest. Look for the message that says
Wrote profiles to /tmp/53dace (symlink /tmp/heap_profile-latest)
The raw-trace and heap_dump.* (pprof) files can be visualized with https://ui.perfetto.dev.Prerequisites
- A Linux machine on x86_64, ARM, or ARM64.
Instructions
Download the heap_profile script:
curl -LO https://raw.githubusercontent.com/google/perfetto/main/tools/heap_profile
chmod +x heap_profileThen run the host subcommand, passing the binary you want to profile after
--: