| # AppMemoryTest (smoldroid) |
| |
| 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. |
| |
| ## Running smoldroid on a local device |
| |
| 1. Connect a device over ADB (a local physical device, a virtual `acloud` |
| device, etc.) |
| 2. From the root of your Android checkout, run `source build/envsetup.sh` and |
| `lunch <target>`, e.g. `lunch cheetah-trunk_staging-userdebug`. |
| 3. Run `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](http://go/smoldroid). |
| |
| ## Understanding smoldroid metrics |
| |
| 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](https://developer.android.com/topic/performance/tracing), |
| meaning that it can be opened in the [Perfetto UI](https://ui.perfetto.dev/) and |
| supports |
| [PerfettoSQL](https://perfetto.dev/docs/analysis/perfetto-sql-getting-started) |
| 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. |
| |
| ```sql |
| 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 | |
| | ... | ... | |