From 72602ce6fbc283398d5353d1c7d3e146fd533810 Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Sun, 27 Sep 2020 15:32:10 -0400 Subject: [PATCH] tracing-context: optimize Visit impl (#94) * tracing-context: optimize Visit impl --- .github/workflows/ci.yml | 2 +- metrics-tracing-context/.gitignore | 3 + metrics-tracing-context/Cargo.toml | 9 + metrics-tracing-context/benches/visit.rs | 183 ++++++++++++++++++ metrics-tracing-context/src/lib.rs | 2 +- .../src/tracing_integration.rs | 28 ++- metrics-util/benches/bucket.rs | 9 +- metrics-util/benches/registry.rs | 5 +- metrics-util/benches/streaming_integers.rs | 9 +- 9 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 metrics-tracing-context/.gitignore create mode 100644 metrics-tracing-context/benches/visit.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 217422d..4ae5e61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - rust_version: ['1.36.0', 'stable', 'nightly'] + rust_version: ['1.42.0', 'stable', 'nightly'] os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v1 diff --git a/metrics-tracing-context/.gitignore b/metrics-tracing-context/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/metrics-tracing-context/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/metrics-tracing-context/Cargo.toml b/metrics-tracing-context/Cargo.toml index c7a0af1..f51c9b1 100644 --- a/metrics-tracing-context/Cargo.toml +++ b/metrics-tracing-context/Cargo.toml @@ -15,12 +15,21 @@ readme = "README.md" categories = ["development-tools::debugging"] keywords = ["metrics", "tracing"] +[lib] +bench = false + +[[bench]] +name = "visit" +harness = false + [dependencies] metrics = { version = "0.13.0-alpha.1", path = "../metrics", features = ["std"] } metrics-util = { version = "0.4.0-alpha.1", path = "../metrics-util" } tracing = "0.1" tracing-core = "0.1" tracing-subscriber = "0.2" +itoa = "0.4" [dev-dependencies] +criterion = "0.3" parking_lot = "0.11" diff --git a/metrics-tracing-context/benches/visit.rs b/metrics-tracing-context/benches/visit.rs new file mode 100644 index 0000000..ed98676 --- /dev/null +++ b/metrics-tracing-context/benches/visit.rs @@ -0,0 +1,183 @@ +use criterion::{criterion_group, criterion_main, BatchSize, Benchmark, Criterion}; +use metrics_tracing_context::Labels; +use tracing::Metadata; +use tracing_core::{ + field::Visit, + metadata, + metadata::{Kind, Level}, + Callsite, Interest, +}; + +const BATCH_SIZE: usize = 1000; + +static CALLSITE: TestCallsite = TestCallsite; +static CALLSITE_METADATA: Metadata = metadata! { + name: "test", + target: module_path!(), + level: Level::DEBUG, + fields: &["test"], + callsite: &CALLSITE, + kind: Kind::SPAN, +}; + +fn visit_benchmark(c: &mut Criterion) { + c.bench( + "visit", + Benchmark::new("record_str", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_str(&field, "test test"); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_bool[true]", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_bool(&field, true); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_bool[false]", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_bool(&field, false); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_i64", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_i64(&field, -3423432); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_u64", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_u64(&field, 3423432); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_debug", |b| { + let debug_struct = DebugStruct::new(); + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_debug(&field, &debug_struct); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_debug[bool]", |b| { + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_debug(&field, &true); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_debug[i64]", |b| { + let value: i64 = -3423432; + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_debug(&field, &value); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }) + .with_function("record_debug[u64]", |b| { + let value: u64 = 3423432; + let field = CALLSITE + .metadata() + .fields() + .field("test") + .expect("test field missing"); + b.iter_batched_ref( + || Labels(Vec::with_capacity(BATCH_SIZE)), + |labels| { + labels.record_debug(&field, &value); + }, + BatchSize::NumIterations(BATCH_SIZE as u64), + ) + }), + ); +} + +#[derive(Debug)] +struct DebugStruct { + field1: String, + field2: u64, +} + +impl DebugStruct { + pub fn new() -> DebugStruct { + DebugStruct { + field1: format!("yeehaw!"), + field2: 324242343243, + } + } +} + +struct TestCallsite; + +impl Callsite for TestCallsite { + fn set_interest(&self, _interest: Interest) {} + fn metadata(&self) -> &Metadata<'_> { + &CALLSITE_METADATA + } +} + +criterion_group!(benches, visit_benchmark); +criterion_main!(benches); diff --git a/metrics-tracing-context/src/lib.rs b/metrics-tracing-context/src/lib.rs index c1b9368..1129556 100644 --- a/metrics-tracing-context/src/lib.rs +++ b/metrics-tracing-context/src/lib.rs @@ -63,7 +63,7 @@ pub mod label_filter; mod tracing_integration; pub use label_filter::LabelFilter; -pub use tracing_integration::{MetricsLayer, SpanExt}; +pub use tracing_integration::{Labels, MetricsLayer, SpanExt}; /// [`TracingContextLayer`] provides an implementation of a [`metrics::Layer`] /// for [`TracingContext`]. diff --git a/metrics-tracing-context/src/tracing_integration.rs b/metrics-tracing-context/src/tracing_integration.rs index c68040f..9d07340 100644 --- a/metrics-tracing-context/src/tracing_integration.rs +++ b/metrics-tracing-context/src/tracing_integration.rs @@ -6,7 +6,12 @@ use tracing_core::span::{Attributes, Id, Record}; use tracing_core::{field::Visit, Dispatch, Field, Subscriber}; use tracing_subscriber::{layer::Context, registry::LookupSpan, Layer}; -struct Labels(Vec