proxy: add benchmark for custom json logging vs official fmt logger

This commit is contained in:
Folke Behrens
2025-02-06 11:12:53 +01:00
parent 5c934efb29
commit ef737e7d7c
5 changed files with 141 additions and 7 deletions

1
Cargo.lock generated
View File

@@ -5303,6 +5303,7 @@ dependencies = [
"clashmap",
"compute_api",
"consumption_metrics",
"criterion",
"ecdsa 0.16.9",
"ed25519-dalek",
"env_logger",

View File

@@ -120,6 +120,7 @@ workspace_hack.workspace = true
[dev-dependencies]
assert-json-diff.workspace = true
camino-tempfile.workspace = true
criterion.workspace = true
fallible-iterator.workspace = true
flate2.workspace = true
tokio-tungstenite.workspace = true
@@ -130,3 +131,8 @@ walkdir.workspace = true
rand_distr = "0.4"
tokio-postgres.workspace = true
tracing-test = "0.2"
[[bench]]
name = "logging"
harness = false

127
proxy/benches/logging.rs Normal file
View File

@@ -0,0 +1,127 @@
use std::io;
use criterion::{Criterion, criterion_group, criterion_main};
use proxy::logging::{Clock, JsonLoggingLayer};
use tracing_subscriber::prelude::*;
struct DevNullWriter;
impl proxy::logging::MakeWriter for DevNullWriter {
fn make_writer(&self) -> impl io::Write {
DevNullWriter
}
}
impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for DevNullWriter {
type Writer = DevNullWriter;
fn make_writer(&'a self) -> Self::Writer {
DevNullWriter
}
}
impl io::Write for DevNullWriter {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
Ok(criterion::black_box(buf).len())
}
#[inline(always)]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
struct FixedClock;
impl Clock for FixedClock {
fn now(&self) -> chrono::DateTime<chrono::Utc> {
const { chrono::DateTime::from_timestamp_nanos(1747859990_000_000_000).to_utc() }
}
}
pub fn bench_logging(c: &mut Criterion) {
c.bench_function("text fmt current", |b| {
let registry = tracing_subscriber::Registry::default().with(
tracing_subscriber::fmt::layer()
.with_ansi(false)
.with_target(false)
.with_writer(DevNullWriter),
);
tracing::subscriber::with_default(registry, || {
tracing::info_span!("span1", a = 42, b = true, c = "string").in_scope(|| {
tracing::info_span!("span2", a = 42, b = true, c = "string").in_scope(|| {
b.iter(|| {
tracing::error!(a = 42, b = true, c = "string", "message field");
})
});
});
});
});
c.bench_function("text fmt full", |b| {
let registry = tracing_subscriber::Registry::default().with(
tracing_subscriber::fmt::layer()
.with_level(true)
.with_file(true)
.with_line_number(true)
.with_target(true)
.with_thread_ids(true)
.with_writer(DevNullWriter),
);
tracing::subscriber::with_default(registry, || {
tracing::info_span!("span1", a = 42, b = true, c = "string").in_scope(|| {
tracing::info_span!("span2", a = 42, b = true, c = "string").in_scope(|| {
b.iter(|| {
tracing::error!(a = 42, b = true, c = "string", "message field");
})
});
});
});
});
c.bench_function("json fmt", |b| {
let registry = tracing_subscriber::Registry::default().with(
tracing_subscriber::fmt::layer()
.with_level(true)
.with_file(true)
.with_line_number(true)
.with_target(true)
.with_thread_ids(true)
.with_writer(DevNullWriter)
.json(),
);
tracing::subscriber::with_default(registry, || {
tracing::info_span!("span1", a = 42, b = true, c = "string").in_scope(|| {
tracing::info_span!("span2", a = 42, b = true, c = "string").in_scope(|| {
b.iter(|| {
tracing::error!(a = 42, b = true, c = "string", "message field");
})
});
});
});
});
c.bench_function("json custom", |b| {
let registry = tracing_subscriber::Registry::default().with(JsonLoggingLayer::new(
FixedClock,
DevNullWriter,
&["a"],
));
tracing::subscriber::with_default(registry, || {
tracing::info_span!("span1", a = 42, b = true, c = "string").in_scope(|| {
tracing::info_span!("span2", a = 42, b = true, c = "string").in_scope(|| {
b.iter(|| {
tracing::error!(a = 42, b = true, c = "string", "message field");
})
});
});
});
});
}
criterion_group!(benches, bench_logging);
criterion_main!(benches);

View File

@@ -93,7 +93,7 @@ mod ext;
mod http;
mod intern;
mod jemalloc;
mod logging;
pub mod logging;
mod metrics;
mod parse;
mod pglb;

View File

@@ -148,11 +148,11 @@ impl LogFormat {
}
}
trait MakeWriter {
pub trait MakeWriter {
fn make_writer(&self) -> impl io::Write;
}
struct StderrWriter {
pub struct StderrWriter {
stderr: io::Stderr,
}
@@ -164,11 +164,11 @@ impl MakeWriter for StderrWriter {
}
// TODO: move into separate module or even separate crate.
trait Clock {
pub trait Clock {
fn now(&self) -> DateTime<Utc>;
}
struct RealClock;
pub struct RealClock;
impl Clock for RealClock {
#[inline]
@@ -203,7 +203,7 @@ type CallsiteMap<T> =
papaya::HashMap<callsite::Identifier, T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
/// Implements tracing layer to handle events specific to logging.
struct JsonLoggingLayer<C: Clock, W: MakeWriter> {
pub struct JsonLoggingLayer<C: Clock, W: MakeWriter> {
clock: C,
writer: W,
@@ -217,7 +217,7 @@ struct JsonLoggingLayer<C: Clock, W: MakeWriter> {
}
impl<C: Clock, W: MakeWriter> JsonLoggingLayer<C, W> {
fn new(clock: C, writer: W, extract_fields: &'static [&'static str]) -> Self {
pub fn new(clock: C, writer: W, extract_fields: &'static [&'static str]) -> Self {
JsonLoggingLayer {
clock,
skipped_field_indices: CallsiteMap::default(),