heapprofd - Android Heap Profiler

heapprofd allows you to attribute memory usage to functions for Android services and apps.

For documentation, see https://perfetto.dev/docs/data-sources/native-heap-profiler.

For design doc, see https://perfetto.dev/docs/design-docs/heapprofd-design.

GN Targets

Factories

android: connects to the system heapprofd. The client API will need to have been built at exactly the same version. This means this can only be used by the API shipped in the platform.

standalone: executes an in-process heapprofd. Can be used on old platform versions.

noop: ignores all calls to the client API. This can be used as a stand-in when compiling, or when executing without profiling.

Interceptors

bionic: uses bionic malloc dispatch to intercept allocation functions on Android. This works by placing a library on a pre-defined path, which gets loaded by Bionic.

glibc: generates a library exposing the allocation functions. This library should be used for LD_PRELOAD and uses the glibc specific symbols like __libc_malloc to use the system allocator.

Shared libraries

GN targetfactoryinterceptordistribution
heapprofd_clientandroidbionicplatform
heapprofd_client_apiandroidnoneplatform
heapprofd_glibc_preloadstandaloneglibcunbundled
heapprofd_standalone_clientstandalonenoneunbundled
heapprofd_api_noopnoopnoneunbundled

Heap profile heapprofd

For development, you might want to get a heap profile of heapprofd while it is profiling something else. For that reason, we allow two heapprofds to run on the system. The secondary heapprofd can then profile your primary one.

To do this, first make sure that heapprofd is running by setting the property

adb shell su root setprop persist.heapprofd.enable 1

Take note of its PID.

adb shell ps -e | grep heapprofd

Then, move away the primary heapprofd socket to make space for the secondary one

adb shell su root mv /dev/socket/heapprofd /dev/socket/heapprofd_primary

Start the secondary heapprofd

adb shell su root start heapprofd_secondary

Now we can start the profile of the primary heapprofd (using the secondary). Leave this session running.

tools/heap_profile -p ${PID_FROM_ABOVE}

Now move back the original socket

adb shell su root unlink /dev/socket/heapprofd
adb shell su root mv /dev/socket/heapprofd_primary /dev/socket/heapprofd

Now all subsequent profiles will be done on the primary heapprofd again, with the secondary observing it.