tree: f80accd060fa9223e8fcd7fefdb87a9a0c5c2700
  1. __init__.py
  2. BUILD.gn
  3. README.md
  4. tp_shell_test.py
  5. tp_utils.py
src/performance/lib/tp_shell/README.md

Perfetto Trace Processor Wrapper Library (tp_shell)

A high-performance, persistent RPC-based Python wrapper around the official Perfetto Trace Processor SDK.

This library packages the prebuilt host trace_processor_shell binary hermetically as a module resource. Using the Perfetto python Library, it starts the shell as a background daemon and executes SQL queries over a RPC connection which sends and receives protobuf messages. This ensures the trace is ingested and parsed only once, improving the performance for scripts executing multi-query analysis.

Implementation notes of interest:

  • This library handles the incompatibilities between the Perfetto GN python_library rules and the Fuchsia python_library rules implementation by referencing the source files from the perfetto source in this BUILD.gn file.

  • This library implements FuchsiaPlatformDelegate which is the Fuchsia specific implementation of Pefetto's PlatformDelegate. This allows us to use the prebuilt trace_processor_shell included in-tree vs. the default behavior of trying to download it from the cloud and cache it.

  • Also included internal to the library are the compiled protobufs needed to make the RPC calls to trace_processor_shell. These are internal to the library and users of the library do not need to interact with protobufs directly.

  • The library includes custom HttpUriResolver and HttpsUriResolver implementations registered with FuchsiaPlatformDelegate. This allows PerfettoTraceProcessor to directly accept ui.perfetto.dev permalinks and direct HTTP/HTTPS URLs as input, resolving metadata and streaming traces over the network without requiring local download steps.

  • The library includes a copy of the trace_processor_shell so if the path to a local copy is not specified, the library will use the bundled copy. This is useful for agent skills and use outside the Fuchsia build directory.


1. Adding to BUILD.gn

To use this library in your Python tool or library, add the target dependency //src/performance/lib/tp_shell to your BUILD.gn file.

Example: For a Python Library

import("//build/python/python_library.gni")

python_library("my_perf_library") {
  source_root = "."
  sources = [
    "analyzer.py",
  ]
  # Depend on tp_shell to make it importable at runtime
  library_deps = [
    "//src/performance/lib/tp_shell",
  ]
  enable_mypy = true
}

Example: For a Python Binary / CLI Tool

import("//build/python/python_binary.gni")

python_binary("my_perf_tool") {
  main_source = "bin/main.py"
  deps = [
    "//src/performance/lib/tp_shell",
  ]
  enable_mypy = true
}

2. Using in Python

Import the PerfettoTraceProcessor class and instantiate it. When packaged correctly via BUILD.gn, the library is completely zero-configuration and automatically resolves its bundled prebuilt binary.

Standard Context Manager Pattern (Recommended)

Using the context manager ensures that the background HTTPD server is cleanly shut down as soon as the with block exits.

from tp_shell import PerfettoTraceProcessor

def analyze_trace(trace_path: str) -> None:
    # Zero-configuration: binary is resolved automatically from packaged resources
    with PerfettoTraceProcessor(trace_path) as tp:
        # Run a query: returns a list of dictionaries where keys are column names
        query = """
            SELECT name, dur / 1000000.0 as dur_ms
            FROM slice
            WHERE category = 'benchmark'
            ORDER BY dur DESC
            LIMIT 5
        """
        results = tp.run_query(query)

        for row in results:
            print(f"Slice: {row['name']} took {row['dur_ms']:.2f} ms")

Direct Instantiation

If you cannot use a with statement, you must call .close() explicitly to terminate the background subprocess.

from tp_shell import PerfettoTraceProcessor

tp = PerfettoTraceProcessor("path/to/trace.fxt")
try:
    results = tp.run_query("SELECT count(*) as cnt FROM slice")
    print(f"Total slices: {results[0]['cnt']}")
finally:
    # Always close to prevent zombie background daemons
    tp.close()

Remote Permalinks and URLs

PerfettoTraceProcessor natively accepts ui.perfetto.dev permalinks and direct HTTP/HTTPS URLs as input. The trace metadata is resolved and streamed directly over the network without requiring a local .fxt download step or disk storage:

from tp_shell import PerfettoTraceProcessor

# Pass a ui.perfetto.dev permalink or HTTP/HTTPS trace URL directly
permalink = "https://ui.perfetto.dev/#!/?s=0fdf12cb1d57131188fd93b6cd857865156e8f5b"
with PerfettoTraceProcessor(permalink) as tp:
    results = tp.run_query("SELECT count(1) as slice_count FROM slice")
    print(f"Total slices in permalink: {results[0]['slice_count']}")

3. Explicit Binary Overrides

By default, the library resolves its bundled resource. If you need to test with a custom version of the trace_processor_shell executable, you can pass the path explicitly:

tp = PerfettoTraceProcessor(
    trace_path="path/to/trace.fxt",
    tp_shell_path="/path/to/custom/trace_processor_shell"
)

If the binary cannot be resolved from either packaged resources or an explicit path, a FileNotFoundError will be raised.