use std::{ fs::File, sync::{Arc, Mutex}, }; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use quanta::Mock; use reqray::{CallTreeCollector, CallTreeCollectorBuilder, FinishedCallTreeProcessor}; use tracing::info; use tracing_subscriber::fmt; use tracing_subscriber::prelude::*; #[tracing::instrument] fn one_ns(mock: &Mock) { info!("one_ns"); mock.increment(1); } #[tracing::instrument] fn compound_call(mock: &Mock) { mock.increment(10); one_ns(mock); mock.increment(100); one_ns(mock); for _ in 0..10 { one_ns(mock); } mock.increment(1000); } pub fn sync_compound(c: &mut Criterion) { let (_clock, mock) = quanta::Clock::mock(); c.bench_function("without subscriber", |b| { b.iter(|| compound_call(black_box(&mock))) }); c.bench_function("log with layers", |b| { let f = File::create("benches_without_calltree.txt").unwrap(); let fmt_layer = fmt::layer() .with_thread_ids(true) .without_time() .with_target(false) .with_writer(f); let subscriber = tracing_subscriber::registry().with(fmt_layer); tracing::subscriber::with_default(subscriber, || { b.iter(|| compound_call(black_box(&mock))) }); }); c.bench_function("log with call tree collector", |b| { let call_tree_collector = CallTreeCollector::default(); let f = File::create("benches_with_calltree.txt").unwrap(); let fmt_layer = fmt::layer() .with_thread_ids(true) .without_time() .with_target(false) .with_writer(f); let subscriber = tracing_subscriber::registry() .with(call_tree_collector) .with(fmt_layer); tracing::subscriber::with_default(subscriber, || { b.iter(|| compound_call(black_box(&mock))) }); }); c.bench_function("log with silent call tree collector", |b| { let counting = CountingCallTreeProcessor::default(); let call_tree_collector = CallTreeCollectorBuilder::default().build_with_collector(counting.clone()); let f = File::create("benches_with_silent_calltree.txt").unwrap(); let fmt_layer = fmt::layer() .with_thread_ids(true) .without_time() .with_target(false) .with_writer(f); let subscriber = tracing_subscriber::registry() .with(call_tree_collector) .with(fmt_layer); tracing::subscriber::with_default(subscriber, || { b.iter(|| compound_call(black_box(&mock))) }); assert!(*counting.root_child_count.lock().unwrap() > 0); }); } #[derive(Default, Clone)] struct CountingCallTreeProcessor { root_child_count: Arc>, } impl FinishedCallTreeProcessor for CountingCallTreeProcessor { fn process_finished_call(&self, pool: reqray::CallPathPool) { let mut locked = self.root_child_count.lock().unwrap(); *locked += pool.root().children().count(); } } criterion_group!(benches, sync_compound); criterion_main!(benches);