xref: /aosp_15_r20/system/extras/libatrace_rust/README.md (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker# libatrace_rust - ATrace bindings for Rust
2*288bf522SAndroid Build Coastguard Worker
3*288bf522SAndroid Build Coastguard WorkerWrapper library for ATrace methods from libcutils.
4*288bf522SAndroid Build Coastguard Worker
5*288bf522SAndroid Build Coastguard Worker## Quick start
6*288bf522SAndroid Build Coastguard Worker
7*288bf522SAndroid Build Coastguard Worker### Using ATrace bindings directly
8*288bf522SAndroid Build Coastguard Worker
9*288bf522SAndroid Build Coastguard WorkerAdd the library to your `rustlibs` in `Android.bp`:
10*288bf522SAndroid Build Coastguard Worker
11*288bf522SAndroid Build Coastguard Worker```text
12*288bf522SAndroid Build Coastguard Workerrustlibs: [
13*288bf522SAndroid Build Coastguard Worker    ...
14*288bf522SAndroid Build Coastguard Worker    "libatrace_rust",
15*288bf522SAndroid Build Coastguard Worker    ...
16*288bf522SAndroid Build Coastguard Worker],
17*288bf522SAndroid Build Coastguard Worker```
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard WorkerCall tracing methods:
20*288bf522SAndroid Build Coastguard Worker
21*288bf522SAndroid Build Coastguard Worker```rust
22*288bf522SAndroid Build Coastguard Workerfn important_function() {
23*288bf522SAndroid Build Coastguard Worker    // Use this macro to trace a function.
24*288bf522SAndroid Build Coastguard Worker    atrace::trace_method!(AtraceTag::App);
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker    if condition {
27*288bf522SAndroid Build Coastguard Worker        // Use a scoped event to trace inside a scope.
28*288bf522SAndroid Build Coastguard Worker        let _event = atrace::begin_scoped_event(AtraceTag::App, "Inside a scope");
29*288bf522SAndroid Build Coastguard Worker        ...
30*288bf522SAndroid Build Coastguard Worker    }
31*288bf522SAndroid Build Coastguard Worker
32*288bf522SAndroid Build Coastguard Worker    // Or just use the wrapped API directly.
33*288bf522SAndroid Build Coastguard Worker    atrace::atrace_begin(AtraceTag::App, "My event");
34*288bf522SAndroid Build Coastguard Worker    ...
35*288bf522SAndroid Build Coastguard Worker    atrace::atrace_end(AtraceTag::App)
36*288bf522SAndroid Build Coastguard Worker}
37*288bf522SAndroid Build Coastguard Worker```
38*288bf522SAndroid Build Coastguard Worker
39*288bf522SAndroid Build Coastguard WorkerSee more in the [example](./example/src/main.rs).
40*288bf522SAndroid Build Coastguard Worker
41*288bf522SAndroid Build Coastguard WorkerYou're all set! Now you can collect a trace with your favorite tracing tool like
42*288bf522SAndroid Build Coastguard Worker[Perfetto](https://perfetto.dev/docs/data-sources/atrace).
43*288bf522SAndroid Build Coastguard Worker
44*288bf522SAndroid Build Coastguard Worker### Using the tracing crate
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard WorkerYou can use the ATrace layer for the [tracing](https://docs.rs/tracing/latest/tracing/) crate.
47*288bf522SAndroid Build Coastguard WorkerCompared to using the bindings directly, it has better instrumentation points and customizability.
48*288bf522SAndroid Build Coastguard WorkerThe main drawback is lower performance. See the [Performance](#performance) section below for more
49*288bf522SAndroid Build Coastguard Workerinformation.
50*288bf522SAndroid Build Coastguard Worker
51*288bf522SAndroid Build Coastguard WorkerAdd the tracing libraries to your `rustlibs` in `Android.bp`:
52*288bf522SAndroid Build Coastguard Worker
53*288bf522SAndroid Build Coastguard Worker```text
54*288bf522SAndroid Build Coastguard Worker    rustlibs: [
55*288bf522SAndroid Build Coastguard Worker        ...
56*288bf522SAndroid Build Coastguard Worker        "libatrace_tracing_subscriber",
57*288bf522SAndroid Build Coastguard Worker        "libtracing_subscriber",
58*288bf522SAndroid Build Coastguard Worker        "libtracing",
59*288bf522SAndroid Build Coastguard Worker        ...
60*288bf522SAndroid Build Coastguard Worker    ],
61*288bf522SAndroid Build Coastguard Worker```
62*288bf522SAndroid Build Coastguard Worker
63*288bf522SAndroid Build Coastguard Worker[Initialize](https://docs.rs/tracing/latest/tracing/index.html#in-executables) the subscriber
64*288bf522SAndroid Build Coastguard Workerbefore calling the tracing methods, usually somewhere in the beginning of `main()`.
65*288bf522SAndroid Build Coastguard Worker
66*288bf522SAndroid Build Coastguard Worker```rust
67*288bf522SAndroid Build Coastguard Worker// Initialize the subscriber, panic if it fails.
68*288bf522SAndroid Build Coastguard Workertracing_subscriber::registry()
69*288bf522SAndroid Build Coastguard Worker        .with(AtraceSubscriber::default().with_filter())
70*288bf522SAndroid Build Coastguard Worker        .init();
71*288bf522SAndroid Build Coastguard Worker```
72*288bf522SAndroid Build Coastguard Worker
73*288bf522SAndroid Build Coastguard WorkerThe subscriber defaults to `AtraceTag::App`. Use other tags by creating the subscriber with
74*288bf522SAndroid Build Coastguard Worker`AtraceSubscriber::new(tag: AtraceTag)`.
75*288bf522SAndroid Build Coastguard Worker
76*288bf522SAndroid Build Coastguard WorkerYou can combine the subscriber with other
77*288bf522SAndroid Build Coastguard Worker[layers](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/index.html). In
78*288bf522SAndroid Build Coastguard Workerthat case, omit `with_filter()` from the `AtraceSubscriber` initialization - it is an optimization
79*288bf522SAndroid Build Coastguard Workerthat disables instrumentation points when ATrace is disabled and it would affect other layers as
80*288bf522SAndroid Build Coastguard Workerwell.
81*288bf522SAndroid Build Coastguard Worker
82*288bf522SAndroid Build Coastguard WorkerNow you can
83*288bf522SAndroid Build Coastguard Worker[record spans and events](https://docs.rs/tracing/latest/tracing/index.html#recording-spans-and-events):
84*288bf522SAndroid Build Coastguard Worker
85*288bf522SAndroid Build Coastguard Worker```rust
86*288bf522SAndroid Build Coastguard Worker// This macro would automatically create and enter a span with function name and arguments.
87*288bf522SAndroid Build Coastguard Worker#[tracing::instrument]
88*288bf522SAndroid Build Coastguard Workerfn important_function() {
89*288bf522SAndroid Build Coastguard Worker    if condition {
90*288bf522SAndroid Build Coastguard Worker        // Use span! to trace inside a scope.
91*288bf522SAndroid Build Coastguard Worker        let _entered = tracing::span!(tracing::Level::TRACE, "Inside a scope").entered();
92*288bf522SAndroid Build Coastguard Worker        ...
93*288bf522SAndroid Build Coastguard Worker    }
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Worker    // Use event! to record an instant event.
96*288bf522SAndroid Build Coastguard Worker    // You can annotate spans and events with fields. They will be appended to the end of
97*288bf522SAndroid Build Coastguard Worker    // the Atrace event.
98*288bf522SAndroid Build Coastguard Worker    tracing::info!(field="value", "My event");
99*288bf522SAndroid Build Coastguard Worker}
100*288bf522SAndroid Build Coastguard Worker```
101*288bf522SAndroid Build Coastguard Worker
102*288bf522SAndroid Build Coastguard WorkerSee more in the [example](./example/src/tracing_subscriber_sample.rs) and check out the docs for
103*288bf522SAndroid Build Coastguard Workerthe [tracing](https://docs.rs/tracing/latest/tracing/index.html) and
104*288bf522SAndroid Build Coastguard Worker[tracing-subscriber](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/index.html)
105*288bf522SAndroid Build Coastguard Workercrates.
106*288bf522SAndroid Build Coastguard Worker
107*288bf522SAndroid Build Coastguard Worker## Performance
108*288bf522SAndroid Build Coastguard Worker
109*288bf522SAndroid Build Coastguard WorkerThis section is an overview, you can find specific numbers in
110*288bf522SAndroid Build Coastguard Worker[benchmark/README.md](./benchmark/README.md).
111*288bf522SAndroid Build Coastguard Worker
112*288bf522SAndroid Build Coastguard Worker### ATrace bindings
113*288bf522SAndroid Build Coastguard Worker
114*288bf522SAndroid Build Coastguard WorkerWhen tracing is enabled, you can expect 1-10 us per event - this is a significant cost that may
115*288bf522SAndroid Build Coastguard Workeraffect the performance of hot high-frequency methods. When the events are disabled, calling them is
116*288bf522SAndroid Build Coastguard Workercheap - on the order of 5-10 ns. There is a 10-20% overhead from the wrapper, mostly caused by
117*288bf522SAndroid Build Coastguard Workerstring conversion when tracing is enabled.
118*288bf522SAndroid Build Coastguard Worker
119*288bf522SAndroid Build Coastguard Worker### Tracing subscriber
120*288bf522SAndroid Build Coastguard Worker
121*288bf522SAndroid Build Coastguard WorkerThe subscriber uses the bindings and adds its own overhead that depends on usage:
122*288bf522SAndroid Build Coastguard Worker
123*288bf522SAndroid Build Coastguard Worker* With tracing disabled and subscriber created `with_filter`, events cost around 30 ns. Not using
124*288bf522SAndroid Build Coastguard Worker  the filter brings the cost up to 100-400 ns per event.
125*288bf522SAndroid Build Coastguard Worker* Instant events (`event!`) add roughly 200 ns to the bindings - 1.5 vs 1.3 us.
126*288bf522SAndroid Build Coastguard Worker* Spans (`span!`) are roughly 400 ns slower - 2.8 vs 2.4 us.
127*288bf522SAndroid Build Coastguard Worker* Using [fields](https://docs.rs/tracing/latest/tracing/index.html#recording-fields) adds time
128*288bf522SAndroid Build Coastguard Worker  that depends on the amount of the fields and the cost of converting them to strings. Typically
129*288bf522SAndroid Build Coastguard Worker  it is around an extra 500 ns per event and an extra 1 us for a span.
130