blob: 2756f3dd2d94d9a690c1218e3ddc7d624d064bda [file] [view] [edit]
# 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
```gn
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
```gn
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.
```python
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.
```python
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:
```python
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:
```python
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.