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