blob: 63aed1463fdf161f6f3521ff654ce57f2e98f6c6 [file] [view]
# Fuchsia Standalone Performance Analysis Tool (`perf-analyze`)
`perf-analyze` is a host-side tool designed to perform standalone, automated,
and human-interactive performance analysis on Fuchsia traces. The tool acts as a
CLI orchestrator that delegates trace processing to specialized analysis
plugins.
---
## Subcommands
1. **`query`**: Executes SQL queries to inspect and extract structured data
from traces. Backed by Perfetto's Trace Processor.
2. **`analyze`**: Executes specialized analysis plugins to identify
performance anomalies (e.g., binder delays, jank, CPU starvation).
3. **`visualize`** *(Planned)*: Generates HTML reports, flamegraphs, SVGs, or
deep-link trampoline URLs for the Perfetto UI.
---
## Global Options
* **`--format <json|markdown|text>`**: Specifies the output format (default:
`text`).
* `text`: Unformatted tab-separated values (TSV), ideal for shell
scripting.
* `markdown`: Formatted Markdown tables, ideal for doc insertion.
* `json`: Structured JSON, ideal for automated tool ingestion.
---
## The `query` Subcommand
The `query` subcommand executes SQL queries against a trace file using
Perfetto's Trace Processor.
### Arguments
* **`--trace <path_or_url>`** *(Required)*: File path to a local `.fxt` trace
file or a URL to a remote trace.
* **`--sql <query_string>`**: Executes a single raw SQL query. Mutually
exclusive with `--batch`.
* **`--batch <json_string_or_@filepath>`**: Executes a JSON array of queries
in the format `[{"name": "query_name", "sql": "select ..."}, ...]`. Use
`@filepath` to read the array from a local file. Mutually exclusive with
`--sql`.
---
## Examples
#### 1. Print query help
```shell
fx perf-analyze query --help
```
*Output:*
```
usage: perf-analyze query [-h] --trace TRACE (--sql SQL | --batch BATCH)
options:
-h, --help show this help message and exit
--trace TRACE Trace file path or URL
--sql SQL SQL query to run
--batch BATCH Batch JSON or @file
```
#### 2. Run a single SQL query (default TSV format)
```shell
fx perf-analyze query \
--trace src/performance/perf-analyze/test-data/sample_fxt.fxt \
--sql "select count(*) as cnt from slice"
```
*Output:*
```
cnt
520
```
#### 3. Run a single SQL query (Markdown format)
```shell
fx perf-analyze --format markdown query \
--trace src/performance/perf-analyze/test-data/sample_fxt.fxt \
--sql "select count(*) as cnt from slice"
```
*Output:*
```
| cnt |
| --- |
| 520 |
```
#### 4. Run a batch of queries from a file (JSON format)
```shell
fx perf-analyze --format json query \
--trace src/performance/perf-analyze/test-data/sample_fxt.fxt \
--batch @src/performance/perf-analyze/test-data/sample_queries.json
```
*Output:*
```json
[
{
"name": "slice_count",
"results": [
{
"cnt": 520
}
]
},
{
"name": "process_count",
"results": [
{
"cnt": 2
}
]
}
]
```
## The `analyze` Subcommand
The `analyze` subcommand runs specialized analysis plugins against a trace file
to identify specific performance anomalies.
### Arguments
* **`--trace <path_or_url>`** *(Required)*: File path to a local `.fxt` trace
file or a URL to a remote trace.
* **`--plugin <plugin_name>`** *(Required)*: Name of the analysis plugin to
execute (e.g., `binder`).
* **`--list-plugins`**: Lists all available analysis plugins.
---
## Available Plugins
### `binder` (Starnix Binder Analysis)
Analyzes Starnix binder delays, missed wakeups (scheduling delays),
late-spawned wakers (`SpawnLooper` instant events), thread pool exhaustion
(`no_available_threads` instant events), and process queue depth backlog
(`process_queue_depth` counters).
> [!TIP]
> **Trace Category Recommendation**: Including the `starnix:binder` trace category
> significantly improves the fidelity and depth of binder analysis.
> With `starnix:binder`, the plugin reconstructs full round-trip IPC transaction flows,
> driver queue wait times, thread pool exhaustion signals, and backlog counters.
> If `starnix:binder` is not found in the trace, the plugin issues an explicit notification
> and falls back to best-effort heuristics using `binder_ioctl` slices and `binder:%` thread
> naming patterns.
The plugin executes 5 diagnostic queries:
1. **Missed Wakeups (Wakeup Latencies)**: Identifies scheduling delays (`Runnable` state duration) for binder threads exceeding the threshold.
2. **Binder Delays (Transaction Queue Latencies)**: Identifies completed and incomplete transaction queue latencies exceeding the threshold.
3. **Spawn Looper Events (Late-Spawned Wakers)**: Identifies `SpawnLooper` thread-scoped instant events (`dur = 0`) and their enclosing syscall/ioctl parent slice context when the binder thread pool exhausts available threads.
4. **No Available Threads Events (Thread Pool Exhaustion)**: Identifies `no_available_threads` process-scoped instant events recorded when an incoming command cannot find an idle thread and queues to the process queue.
5. **Binder Process Queue Depth (Counter Summary)**: Summarizes `process_queue_depth` counter track peaks, averages, and sample counts per process.
#### Fallback Behavior Without `starnix:binder`
When the trace does not contain slices under the `starnix:binder` category:
* An initial **Trace Category Status** section is reported recommending the inclusion of `starnix:binder`.
* **Missed Wakeups** and **Binder Delays** fall back to matching `binder_ioctl` slices and `binder:%` / `binder_%` thread names.
* **Spawn Looper Events**, **No Available Threads**, and **Process Queue Depth** return empty result sets with a note indicating the category was not found and that enabling it will strengthen the analysis.
#### Plugin-Specific Arguments
* **`--threshold-ms <float>`**: Threshold for scheduling delay and queue
latency in milliseconds (default: `10.0`). Does not filter instant events or
queue depth counters.
* **`--complete-only`**: Only return complete transactions (default: False,
includes incomplete transactions).
#### Example
```shell
fx perf-analyze --format markdown analyze \
--trace "https://ui.perfetto.dev/#!/?s=b3615b084da54e9a0742dd8f6280de355df4f513" \
--plugin binder \
--threshold-ms 15.0
```
---
### `cpu` (CPU Utilization & Idle Power Diagnostics)
Provides a multi-dimensional diagnostic view of system activity during an idle
trace, identifying timer thrashing, excessive wakeups, per-core utilization and
frequency scaling, async executor overhead, binder IPC chatter, and suspend/wake
lease blockers.
The plugin executes 6 diagnostic queries in prioritized order:
1. **Restless Sleepers (Wakeup Counts)**: Identifies threads with high context
switch / wakeup counts preventing deep sleep (VddMin).
2. **Per-Core Utilization & Processing Rate**: Analyzes core duty cycles
(% active non-idle time) and CPU frequency scaling via Fuchsia kernel
`Processing Rate:CPU:N` counters.
3. **Top CPU Consumers (Usual Suspects)**: Ranks threads by total accumulated
CPU runtime.
4. **Fuchsia Async Executor Overhead**: Measures runtime and slice counts for
async executors managing futures.
5. **Binder IPC Breakdown**: Quantifies Starnix/Android IPC transaction traffic
and latencies broken down by thread and process.
6. **Suspend and Wake Lease Tracking**: Verifies SAG suspend attempts and
attributes active wake leases to components.
#### Plugin-Specific Arguments
* **`--limit <int>`**: Maximum number of rows returned for ranked queries
(default: `15`).
#### Example
```shell
fx perf-analyze --format markdown analyze \
--trace src/performance/perf-analyze/test-data/sample_fxt.fxt \
--plugin cpu \
--limit 10
```
---
## Running Tests
Unit tests are written using standard Python `unittest`. To build and run all
unit tests, execute:
```shell
fx test perf_analyze_test binder_test result_formatter_test cpu_test plugins_test
```