1#![allow(dead_code)]
2use criterion::{black_box, measurement::WallTime, Bencher};
3use tracing::{field, span, Event, Id, Metadata};
4
5use std::{
6 fmt::{self, Write},
7 sync::{Mutex, MutexGuard},
8};
9
10pub fn for_all_recording(
11 group: &mut criterion::BenchmarkGroup<'_, WallTime>,
12 mut iter: impl FnMut(&mut Bencher<'_, WallTime>),
13) {
14 // first, run benchmarks with no subscriber
15 group.bench_function("none", &mut iter);
16
17 // then, run benchmarks with a scoped default subscriber
18 tracing::subscriber::with_default(EnabledSubscriber, || {
19 group.bench_function("scoped", &mut iter)
20 });
21
22 let subscriber = VisitingSubscriber(Mutex::new(String::from("")));
23 tracing::subscriber::with_default(subscriber, || {
24 group.bench_function("scoped_recording", &mut iter);
25 });
26
27 // finally, set a global default subscriber, and run the benchmarks again.
28 tracing::subscriber::set_global_default(EnabledSubscriber)
29 .expect("global default should not have already been set!");
30 let _ = log::set_logger(&NOP_LOGGER);
31 log::set_max_level(log::LevelFilter::Trace);
32 group.bench_function("global", &mut iter);
33}
34
35pub fn for_all_dispatches(
36 group: &mut criterion::BenchmarkGroup<'_, WallTime>,
37 mut iter: impl FnMut(&mut Bencher<'_, WallTime>),
38) {
39 // first, run benchmarks with no subscriber
40 group.bench_function("none", &mut iter);
41
42 // then, run benchmarks with a scoped default subscriber
43 tracing::subscriber::with_default(EnabledSubscriber, || {
44 group.bench_function("scoped", &mut iter)
45 });
46
47 // finally, set a global default subscriber, and run the benchmarks again.
48 tracing::subscriber::set_global_default(EnabledSubscriber)
49 .expect("global default should not have already been set!");
50 let _ = log::set_logger(&NOP_LOGGER);
51 log::set_max_level(log::LevelFilter::Trace);
52 group.bench_function("global", &mut iter);
53}
54
55const NOP_LOGGER: NopLogger = NopLogger;
56
57struct NopLogger;
58
59impl log::Log for NopLogger {
60 fn enabled(&self, _metadata: &log::Metadata) -> bool {
61 true
62 }
63
64 fn log(&self, record: &log::Record) {
65 if self.enabled(record.metadata()) {
66 let mut this = self;
67 let _ = write!(this, "{}", record.args());
68 }
69 }
70
71 fn flush(&self) {}
72}
73
74impl Write for &NopLogger {
75 fn write_str(&mut self, s: &str) -> std::fmt::Result {
76 black_box(s);
77 Ok(())
78 }
79}
80
81/// Simulates a subscriber that records span data.
82struct VisitingSubscriber(Mutex<String>);
83
84struct Visitor<'a>(MutexGuard<'a, String>);
85
86impl<'a> field::Visit for Visitor<'a> {
87 fn record_debug(&mut self, _field: &field::Field, value: &dyn fmt::Debug) {
88 let _ = write!(&mut *self.0, "{:?}", value);
89 }
90}
91
92impl tracing::Subscriber for VisitingSubscriber {
93 fn new_span(&self, span: &span::Attributes<'_>) -> Id {
94 let mut visitor = Visitor(self.0.lock().unwrap());
95 span.record(&mut visitor);
96 Id::from_u64(0xDEAD_FACE)
97 }
98
99 fn record(&self, _span: &Id, values: &span::Record<'_>) {
100 let mut visitor = Visitor(self.0.lock().unwrap());
101 values.record(&mut visitor);
102 }
103
104 fn event(&self, event: &Event<'_>) {
105 let mut visitor = Visitor(self.0.lock().unwrap());
106 event.record(&mut visitor);
107 }
108
109 fn record_follows_from(&self, span: &Id, follows: &Id) {
110 let _ = (span, follows);
111 }
112
113 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
114 let _ = metadata;
115 true
116 }
117
118 fn enter(&self, span: &Id) {
119 let _ = span;
120 }
121
122 fn exit(&self, span: &Id) {
123 let _ = span;
124 }
125}
126
127/// A subscriber that is enabled but otherwise does nothing.
128struct EnabledSubscriber;
129
130impl tracing::Subscriber for EnabledSubscriber {
131 fn new_span(&self, span: &span::Attributes<'_>) -> Id {
132 let _ = span;
133 Id::from_u64(0xDEAD_FACE)
134 }
135
136 fn event(&self, event: &Event<'_>) {
137 let _ = event;
138 }
139
140 fn record(&self, span: &Id, values: &span::Record<'_>) {
141 let _ = (span, values);
142 }
143
144 fn record_follows_from(&self, span: &Id, follows: &Id) {
145 let _ = (span, follows);
146 }
147
148 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
149 let _ = metadata;
150 true
151 }
152
153 fn enter(&self, span: &Id) {
154 let _ = span;
155 }
156
157 fn exit(&self, span: &Id) {
158 let _ = span;
159 }
160}
161