Trace analysis refers to a set of features built into the Perfetto trace processor and Perfetto UI which enrich a trace with extra information synthesized during the import of a trace. There are three features which currently part of this project:
Description for the measure slice
Descriptions attach a human-readable description to a slice in the trace. This can include information like the source of a slice, why a slice is important and links to documentation where the viewer can learn more about the slice. In essence, descriptions act as if an expert was telling the user what the slice means.
For example, consider the inflate
slice which occurs during view inflation in Android. We can add the following description and link:
Description: Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes. Link: https://developer.android.com/reference/android/view/layoutinflater#inflate(int,%20android.view.viewgroup)
Adding a new event just requires a self-contained change to the DescribeSlice
function. The inputs are the table containing all the slices from the trace and the id of the slice which an embedder (e.g. the UI) is requesting a description for. The output is a SliceDescription
which is simply a pair<description, doc link>
.
Currently, all implemented descriptions are based on only the name of the slice itself. However, it is straightforward to extend this to also consider the ancestor slices and other similar properties of the slice and we plan on doing this in the future.
The DescribeSlice
function is exposed to SQL through the describe_slice
table. This table has the following schema:
Name | Type | Meaning |
---|---|---|
description | string | Provides the description for the given slice |
doc_link | string | Provides a hyperlink to documentation which gives more context for the slice |
The table also has a hidden column slice_id
which need to be set equal to the id of the slice that you want to obtain the description from. For example, to get the description and doc link for slice with id 5
:
select description, doc_link from describe_slice where slice_id = 5
You can also join the describe_slice
table with the slice table to obtain descriptions for more than one slice. For example, to get the ts, duration and description for all measure
slices:
select ts, dur, description from slice s join desribe_slice d on s.id = d.slice_id where name = 'measure'
Annotation slice track containing app startups
Annotation counter track added to measure ION allocations
The annotations feature allows creation of new events (slices and counters) from the data in the trace. These events can then be displayed in the UI tracks as if they were part of the trace itself.
This feature is useful as often the data in the trace is very low-level. While this low level information is important to expose for experts to perform deep debugging, often the user is looking to get a high level overview without needing to piece together events from multiple places in the trace.
For example, an app startup in Android spans multiple components including ActivityManager
, system_server
and the newly created app process derived from zygote
. Most users do not need startup broken down to this level of detail; instead they are simply interested in a single slice spanning the whole startup duration.
The annotations feature is tied very closely to metrics subsystem; Often the SQL-based metrics often need to create higher-level abstractions from raw slices as intermediate artifacts. From previous example, the startup metric, it creates the exact launching
slice we want to display in the UI.
The other benefit of aligning the two is that changes in metrics are automatically kept in sync with what the user sees in the UI.
As annotations depend on metrics, the initial steps are same as that of developing a metric. In summary:
TraceMetrics
protoNote: the metric can be just an empty proto message during prototyping or if you think that no summarisation is necessary. However, generally if an event is important enough to display in the UI, it should also be tracked in benchmarks as a metric.
To extend a metric with annotations, a new table or view with the name <metric name>_annotations
needs to be created (the trailing _annotations
suffix in the table name is important). For example, for the android_startup
metric, we create a view named android_startup_annotations
.
The schema of this table/view is as follows:
Name | Type | Presence | Meaning |
---|---|---|---|
track_type | string | Mandatory | ‘slice’ for slices, ‘counter’ for counters |
track_name | string | Mandatory | Name of the track to display in the UI |
ts | int64 | Mandatory | The timestamp of the event (slice or counter) |
dur | int64 | Mandatory for slice, NULL for counter | The duration of the slice |
slice_name | string | Mandatory for slice, NULL for counter | The name of the slice |
value | double | Mandatory for counter, NULL for slice | The value of the counter |
Note: track_name
acts as the track identifier i.e. all events with the same track_name
are placed onto the same track.
Currently, there are a few limitations to what can be displayed with annotations:
0
duration slices with special rendering on the UI side.As annotations are tied to the metrics subsystem, the ComputeMetrics
function in the trace processor API should be called with the appropriate metrics. This will create the <metric_name>_annotations
table/view which can then be queried using the ExectueQuery
function.
Note: We plan at some point to have an API which does not create and return the full metrics proto but instead just executes the queries in the metric.
Alerts are used to draw the attention of the user to interesting parts of the trace; this are usually warnings or errors about anomalies which occured in the trace.
Currently, alerts are not implemented in the trace processor but the annotations feature was designed with them in mind. We plan on adding another column alert_type
(name to be finalized) to the annotations table which can have the value warning
, error
or null
. Depending on this value, the Perfetto UI will flag these events to the user.
Note: we do not plan on supporting case where alerts need to be added to existing events. Instead, new events should be created using annotations and alerts added on these instead; this is because the trace processor storage is append-only.