ADB-based Android performance metric recorder with live TUI and HTML report
Project description
androidperf
A CLI that records Android app runtime performance over ADB — CPU, RAM, network, FPS/jank, battery, thermal, and screen transitions — draws a live terminal dashboard while it runs, and drops a self-contained HTML report at the end.
┌── androidperf · com.example.app · Pixel 7 (sdk 34) samples 42 elapsed 00:41 ──┐
│ screen HomeActivity battery 87% charging 31°C thermal moderate skin 35°C │
├──── CPU ────┬── Memory ─────────┬──── Network ────┬──── FPS ────┐
│ │ │ │ │
│ 19.2 % │ Total PSS 199 MB │ ↓ rx 5 KB/s │ fps 58.2 │
│ ▁▂▄▆█ │ Java 39 MB │ ↑ tx 2 KB/s │ jank 3.1 % │
│ │ Native 44 MB │ │ p95 18 │
│ per-process │ Graphics 20 MB │ ▁▂ │ █▆▄▂▁ │
│ CPU │ ▁▂ │ ▁▂ │ │
└─────────────┴───────────────────┴─────────────────┴─────────────┘
Ctrl+C to stop
Requirements
| Python | 3.11 or newer |
| adb | Android Platform Tools on $PATH. macOS: brew install --cask android-platform-tools. Debian/Ubuntu: sudo apt install adb. Windows/other: https://developer.android.com/tools/releases/platform-tools. Verify with adb version. |
| Android device | Physical device or emulator running Android 7.0 (SDK 24) or newer — dumpsys gfxinfo framestats needs SDK 24+. |
| USB debugging | Enabled in Developer Options, and the host authorized (adb devices shows the serial as device, not unauthorized). |
| Python deps | Installed automatically: adbutils, typer, rich, jinja2, plotly, pandas. |
adb is not a Python package — it's a standalone binary. If androidperf devices says "command not found", that's the missing piece.
Install
pipx install androidperf # recommended — isolated, globally available
# or
pip install androidperf # into the current environment
From source (until the package is on PyPI, or if you want to hack on it):
git clone https://github.com/jitinsharma/androidperf.git
cd androidperf
# Option A — globally available, isolated venv managed by pipx:
pipx install .
pipx install --editable . # if you plan to edit the code
# Option B — a regular venv with the dev extras (pytest, ruff):
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Quickstart
# 1. See connected devices
androidperf devices
# 2. Find the package you want to profile
androidperf packages --filter com.android
# 3. Search app and record
androidperf record
# 3. Launch the app and record for 60s at 1s cadence
androidperf record --package com.android.settings --interval 1 --duration 60
If --package is omitted, record drops into an interactive prompt: type a
substring, pick a number.
Attach to an already-running app instead of launching it:
androidperf record --package com.example.app --no-launch
Stop early with Ctrl+C — the JSON and HTML are still written with whatever
samples were collected. After the session ends, a stat-card panel prints in
the terminal with the same summary numbers that appear in the HTML report.
Each run writes to runs/<timestamp>-<pkg>/:
samples.json— raw time-series data, easy to diff or re-plotreport.html— single self-contained file, opens offline
What gets measured
| Metric | Source |
|---|---|
| CPU % (per-core summed) | top -n 1 -b -p <pid> |
| RAM: PSS / Java / Native / Graphics / Code / Stack | dumpsys meminfo <package> |
| Network rx/tx (per-tick deltas) | /proc/net/xt_qtaguid/stats (falls back to dumpsys netstats --uid=<uid> on Android 10+) |
| Frame rendering rate, jank %, frame p50/p90/p95/p99 | dumpsys gfxinfo <package> (window read directly from Uptime − Stats since for accuracy) |
| Battery: level, temp, voltage, status | dumpsys battery |
| Thermal: status, skin/cpu/gpu/battery °C | dumpsys thermalservice |
| Activity transitions | dumpsys activity activities |
| Active fragment (top-level + deepest visible child) | dumpsys activity <component> — AndroidX FragmentManager apps only |
CPU is reported as top's raw %CPU — i.e., summed across cores. 200% means
the process is using two cores worth of time. This is the same convention
used by Android Studio's CPU profiler.
A note on FPS: Android UI rendering is demand-driven. The app submits a
frame only when something on screen changes (animation tick, scroll, view
invalidation), so frames/sec goes to zero on a static screen — that's
correct, not a bug. androidperf reports it as an activity trace and
leads the smoothness summary with jank % and p95 frame time, which
are the metrics that actually correlate with perceived smoothness.
HTML report
The report opens with a compact screen-timeline swim-lane (Activity row + Fragment row) showing colored segments across the session — one glance tells you what was on screen when. Below that, the metric charts have a unified hover that includes the active activity + fragment at any timestamp, so you can correlate spikes with user navigation without leaving the chart. The report also includes:
- Summary stat cards (averages, peaks, network totals, battery delta).
- Interactive Plotly charts — zoom, pan, hover tooltips, toggle traces in the
legend. No network required to view the report;
plotly.jsis inlined.
Commands
| Command | Purpose |
|---|---|
androidperf devices |
List connected ADB devices. |
androidperf packages [--filter X] [--serial S] [--limit N] |
List installed packages. |
androidperf record --package PKG [...] |
Record a session; write JSON + HTML. |
androidperf report SAMPLES_JSON |
Regenerate HTML from an existing run. |
androidperf version |
Print installed version. |
Development
pytest -q # parser + report tests (no device required)
ruff check src # lint
Parsers live under src/androidperf/collectors/ and are tested against
captured command output in tests/fixtures/. When you hit a device whose
output differs, add a fixture file + an assertion and the parser can be
updated against it without any device plugged in.
Layout
src/androidperf/
├── cli.py # Typer entry point
├── device.py # adb detection, package list, app launch
├── session.py # polling loop, signal handling, JSON writer
├── summary.py # shared summary-card computation (HTML + terminal)
├── collectors/ # cpu, memory, network, fps, battery, thermal, activity, fragments
├── ui/ # live.py (Live dashboard) + summary.py (end-of-run panel)
└── report/ # Jinja2 + Plotly → self-contained HTML
See plan/ for architecture and future-direction docs.
License
MIT.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file androidperf-0.1.2.tar.gz.
File metadata
- Download URL: androidperf-0.1.2.tar.gz
- Upload date:
- Size: 51.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
253643fdbf37364187ee7d82a4c0f0803c1bb58a5b4abcd0f08f99cce69c24ba
|
|
| MD5 |
3ac119ca2129051b14601aa87b597071
|
|
| BLAKE2b-256 |
48dfc29b81ba6bc65f609457347e206a32ed75c8ce95dee9594b03b30ba068a5
|
File details
Details for the file androidperf-0.1.2-py3-none-any.whl.
File metadata
- Download URL: androidperf-0.1.2-py3-none-any.whl
- Upload date:
- Size: 35.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ba7c82f8d32d8691d993c18da7a70bdc9e198aec55f485b6533cc59e639c21a
|
|
| MD5 |
6174908af8e9a4725fc099552fca8ecd
|
|
| BLAKE2b-256 |
2817f3155235d6d0dc88b4308a6a638d8d0a05a4b22691b36f0b332a20ed0187
|