diff options
Diffstat (limited to 'libatrace_rust/README.md')
-rw-r--r-- | libatrace_rust/README.md | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/libatrace_rust/README.md b/libatrace_rust/README.md new file mode 100644 index 00000000..4d4fa898 --- /dev/null +++ b/libatrace_rust/README.md @@ -0,0 +1,129 @@ +# libatrace_rust - ATrace bindings for Rust + +Wrapper library for ATrace methods from libcutils. + +## Quick start + +### Using ATrace bindings directly + +Add the library to your `rustlibs` in `Android.bp`: + +```text +rustlibs: [ + ... + "libatrace_rust", + ... +], +``` + +Call tracing methods: + +```rust +fn important_function() { + // Use this macro to trace a function. + atrace::trace_method!(AtraceTag::App); + + if condition { + // Use a scoped event to trace inside a scope. + let _event = atrace::begin_scoped_event(AtraceTag::App, "Inside a scope"); + ... + } + + // Or just use the wrapped API directly. + atrace::atrace_begin(AtraceTag::App, "My event"); + ... + atrace::atrace_end(AtraceTag::App) +} +``` + +See more in the [example](./example/src/main.rs). + +You're all set! Now you can collect a trace with your favorite tracing tool like +[Perfetto](https://perfetto.dev/docs/data-sources/atrace). + +### Using the tracing crate + +You can use the ATrace layer for the [tracing](https://docs.rs/tracing/latest/tracing/) crate. +Compared to using the bindings directly, it has better instrumentation points and customizability. +The main drawback is lower performance. See the [Performance](#performance) section below for more +information. + +Add the tracing libraries to your `rustlibs` in `Android.bp`: + +```text + rustlibs: [ + ... + "libatrace_tracing_subscriber", + "libtracing_subscriber", + "libtracing", + ... + ], +``` + +[Initialize](https://docs.rs/tracing/latest/tracing/index.html#in-executables) the subscriber +before calling the tracing methods, usually somewhere in the beginning of `main()`. + +```rust +// Initialize the subscriber, panic if it fails. +tracing_subscriber::registry() + .with(AtraceSubscriber::default().with_filter()) + .init(); +``` + +The subscriber defaults to `AtraceTag::App`. Use other tags by creating the subscriber with +`AtraceSubscriber::new(tag: AtraceTag)`. + +You can combine the subscriber with other +[layers](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/index.html). In +that case, omit `with_filter()` from the `AtraceSubscriber` initialization - it is an optimization +that disables instrumentation points when ATrace is disabled and it would affect other layers as +well. + +Now you can +[record spans and events](https://docs.rs/tracing/latest/tracing/index.html#recording-spans-and-events): + +```rust +// This macro would automatically create and enter a span with function name and arguments. +#[tracing::instrument] +fn important_function() { + if condition { + // Use span! to trace inside a scope. + let _entered = tracing::span!(tracing::Level::TRACE, "Inside a scope").entered(); + ... + } + + // Use event! to record an instant event. + // You can annotate spans and events with fields. They will be appended to the end of + // the Atrace event. + tracing::info!(field="value", "My event"); +} +``` + +See more in the [example](./example/src/tracing_subscriber_sample.rs) and check out the docs for +the [tracing](https://docs.rs/tracing/latest/tracing/index.html) and +[tracing-subscriber](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/index.html) +crates. + +## Performance + +This section is an overview, you can find specific numbers in +[benchmark/README.md](./benchmark/README.md). + +### ATrace bindings + +When tracing is enabled, you can expect 1-10 us per event - this is a significant cost that may +affect the performance of hot high-frequency methods. When the events are disabled, calling them is +cheap - on the order of 5-10 ns. There is a 10-20% overhead from the wrapper, mostly caused by +string conversion when tracing is enabled. + +### Tracing subscriber + +The subscriber uses the bindings and adds its own overhead that depends on usage: + +* With tracing disabled and subscriber created `with_filter`, events cost around 30 ns. Not using + the filter brings the cost up to 100-400 ns per event. +* Instant events (`event!`) add roughly 200 ns to the bindings - 1.5 vs 1.3 us. +* Spans (`span!`) are roughly 400 ns slower - 2.8 vs 2.4 us. +* Using [fields](https://docs.rs/tracing/latest/tracing/index.html#recording-fields) adds time + that depends on the amount of the fields and the cost of converting them to strings. Typically + it is around an extra 500 ns per event and an extra 1 us for a span. |