tree: c4d2595d98d7143f43ba156c4206eea233352d51
  1. test-data/
  2. binder.py
  3. binder_test.py
  4. BUILD.gn
  5. cpu.py
  6. cpu_test.py
  7. perf_analyze.py
  8. perf_analyze_test.py
  9. plugins.py
  10. plugins_test.py
  11. query.py
  12. README.md
  13. result_formatter.py
  14. result_formatter_test.py
src/performance/perf-analyze/README.md

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

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)

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)

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)

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:

[
  {
    "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

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

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:

fx test perf_analyze_test binder_test result_formatter_test cpu_test plugins_test