blob: d1718561815465ac6e561613ca1101bc2c0a26fd [file] [view]
# 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 |
| ... | ... |