AppMemoryTest is a test designed to produce low-noise, highly-actionable metrics for Android cold app startups. It starts a barebones Android app, then collects and reports only reproducible and easily-attributable metrics, such as the size and number of items on the app heap or total number of binder transactions emitted by the app process.
This guide provides instructions on how to run AppMemoryTest on a local device and in ABTD, as well as how to analyze output artifacts.
acloud device, etc.)source build/envsetup.sh and lunch <target>, e.g. lunch cheetah-trunk_staging-userdebug.atest AppMemoryTestCases, which will output a few metrics in plain text as well as a path to the directory containing atest output artifacts. In the example below, appmemorytest_app_heap_count and appmemorytest_app_heap_size_bytes are the metric results. /tmp/atest_result/20251222_190845_6fbp6fde will contain a Perfetto trace and a .hprof$ atest AppMemoryTestCases
Atest results and logs directory: /tmp/atest_result/20251222_190845_6fbp6fde
...
arm64-v8a AppMemoryTestCases
----------------------------
arm64-v8a AppMemoryTestCases (1 Test)
[1/1] android.app.memory.tests.AppMemoryTest#testApp: PASSED (12.138s)
appmemorytest_app_heap_count: 14198
appmemorytest_app_heap_size_bytes: 563401
...
Googlers can find more detailed steps at go/smoldroid.
The plain metrics returned after the atest invocation (_heap_count and _heap_size_bytes) refer to the number and size of the objects contained on the barebones test app‘s Java heap after a cold startup. This is directly computed from the .hprof file collected during the test, which can be further inspected with AHAT. The heap object count and size is expected to be fairly stable across test runs, as allocations made during an app startup shouldn’t vary much.
The trace file collected by smoldroid can be analyzed like any other device-side performance trace, meaning that it can be opened in the Perfetto UI and supports PerfettoSQL queries. The metrics/ folder contains a couple of quick sample queries--for example, the SQL in appmemorytest_binder_transactions.textproto can be used to view the full set of binder transactions initiated by the test app during startup.
INCLUDE PERFETTO MODULE android.binder; INCLUDE PERFETTO MODULE android.startup.startups; WITH testhelper_startup AS ( SELECT ts, (ts + dur) AS ts_end FROM android_startups WHERE package = 'android.app.memory.testhelper' LIMIT 1 ) SELECT abt.aidl_name, COALESCE(abt.aidl_name, 'NULL') AS aidl_name_including_nulls FROM android_binder_txns AS abt JOIN testhelper_startup ON ( abt.client_ts >= testhelper_startup.ts AND abt.client_ts < testhelper_startup.ts_end ) WHERE abt.client_process = 'android.app.memory.testhelper'
The query above returns this output:
| aidl_name | aidl_name_including_nulls |
|---|---|
| null | NULL |
| null | NULL |
| AIDL::java::IActivityManager::attachApplication::server | AIDL::java::IActivityManager::attachApplication::server |
| null | NULL |
| AIDL::java::IDisplayManager::getPreferredWideGamutColorSpaceId::server | AIDL::java::IDisplayManager::getPreferredWideGamutColorSpaceId::server |
| AIDL::java::IDisplayManager::getOverlaySupport::server | AIDL::java::IDisplayManager::getOverlaySupport::server |
| AIDL::java::IDisplayManager::getDisplayInfo::server | AIDL::java::IDisplayManager::getDisplayInfo::server |
| AIDL::java::INetworkManagementService::setUidCleartextNetworkPolicy::server | AIDL::java::INetworkManagementService::setUidCleartextNetworkPolicy::server |
| ... | ... |