Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
trace: Improve support for batching field values (#880)
This branch reworks `tokio-trace`'s field recording APIs to improve performance in cases where field values are provided in batches. `tokio-trace` supports recording values for span fields either when the span is constructed, or at any point during its lifetime. In order to support this, the current implementation represents each field value recorded with a separate call to a `Subscriber::record_$TYPE` function. This can incur significant overhead --- for example, if the span data is stored behind a mutex, every call to `record` must reacquire the lock. Providing most or all of the fields on a span up-front as it is constructed is likely to be the common case, but in the current design, this use-case has to pay performance costs in order to support the less common case of adding values post-initialization. Even in situations where some field values are unknown, if a majority are recorded at construction-time, each individual value takes a separate trip through the `record` pipeline. This branch rewrites this API so that all field recording is done by a `ValueSet` type, which groups together multiple values. A subscriber may pass an implementation of `Record` to the `ValueSet`'s `record` function, which will record all the provided values with that recorder. When a span is constructed, the `Subscriber::new_span` method is called with a `ValueSet` containing all the fields provided to the `span!` macro, and additional fields may be recorded either individually or in batches. In addition, the previous implementation of `Event`s on top of `Span`s has been removed and replaced with a new `Event` type which goes through a separate `Subscriber::event` function. Events are always known to have all their values at construction time, since the event cannot live long enough to have more values added. Thus, an `Event` also contains a `ValueSet`. I've added new test-support code for expecting certain fields to be recorded by spans and events, and written new tests to cover this behaviour. I've also updated the example code, and my experience doing so suggests that the new API is also somewhat more ergonomic to use. These changes result in significant improvement on the benchmark that simulates recording multiple fields on a span (`bench_span_with_fields_record`). Before: ``` Running target/release/deps/no_subscriber-a6af9f5aa4934184 running 5 tests test bench_1_atomic_load ... bench: 0 ns/iter (+/- 0) test bench_costly_field_no_subscriber ... bench: 0 ns/iter (+/- 0) test bench_log_no_logger ... bench: 0 ns/iter (+/- 0) test bench_no_span_no_subscriber ... bench: 0 ns/iter (+/- 0) test bench_span_no_subscriber ... bench: 0 ns/iter (+/- 0) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out Running target/release/deps/subscriber-ba753dc1d87e480d running 4 tests test span_no_fields ... bench: 41 ns/iter (+/- 5) test span_repeatedly ... bench: 5,418 ns/iter (+/- 658) test span_with_fields ... bench: 110 ns/iter (+/- 42) test span_with_fields_record ... bench: 1,047 ns/iter (+/- 240) test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out ``` After: ``` Running target/release/deps/no_subscriber-611d60b262fbbcfb running 5 tests test bench_1_atomic_load ... bench: 0 ns/iter (+/- 0) test bench_costly_field_no_subscriber ... bench: 1 ns/iter (+/- 0) test bench_log_no_logger ... bench: 0 ns/iter (+/- 0) test bench_no_span_no_subscriber ... bench: 0 ns/iter (+/- 0) test bench_span_no_subscriber ... bench: 0 ns/iter (+/- 0) test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured; 0 filtered out Running target/release/deps/subscriber-7a1279c84c0d50ff running 4 tests test span_no_fields ... bench: 37 ns/iter (+/- 9) test span_repeatedly ... bench: 4,502 ns/iter (+/- 712) test span_with_fields ... bench: 54 ns/iter (+/- 17) test span_with_fields_record ... bench: 364 ns/iter (+/- 38) test result: ok. 0 passed; 0 failed; 0 ignored; 4 measured; 0 filtered out ``` Signed-off-by: Eliza Weisman <eliza@buoyant.io>
- Loading branch information