1 #![allow(dead_code)]
2 use criterion::{black_box, measurement::WallTime, Bencher};
3 use tracing::{field, span, Event, Id, Metadata};
4
5 use std::{
6 fmt::{self, Write},
7 sync::{Mutex, MutexGuard},
8 };
9
for_all_recording( group: &mut criterion::BenchmarkGroup<'_, WallTime>, mut iter: impl FnMut(&mut Bencher<'_, WallTime>), )10 pub 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
for_all_dispatches( group: &mut criterion::BenchmarkGroup<'_, WallTime>, mut iter: impl FnMut(&mut Bencher<'_, WallTime>), )35 pub 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
55 const NOP_LOGGER: NopLogger = NopLogger;
56
57 struct NopLogger;
58
59 impl log::Log for NopLogger {
enabled(&self, _metadata: &log::Metadata) -> bool60 fn enabled(&self, _metadata: &log::Metadata) -> bool {
61 true
62 }
63
log(&self, record: &log::Record)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
flush(&self)71 fn flush(&self) {}
72 }
73
74 impl Write for &NopLogger {
write_str(&mut self, s: &str) -> std::fmt::Result75 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.
82 struct VisitingSubscriber(Mutex<String>);
83
84 struct Visitor<'a>(MutexGuard<'a, String>);
85
86 impl<'a> field::Visit for Visitor<'a> {
record_debug(&mut self, _field: &field::Field, value: &dyn fmt::Debug)87 fn record_debug(&mut self, _field: &field::Field, value: &dyn fmt::Debug) {
88 let _ = write!(&mut *self.0, "{:?}", value);
89 }
90 }
91
92 impl tracing::Subscriber for VisitingSubscriber {
new_span(&self, span: &span::Attributes<'_>) -> Id93 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
record(&self, _span: &Id, values: &span::Record<'_>)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
event(&self, event: &Event<'_>)104 fn event(&self, event: &Event<'_>) {
105 let mut visitor = Visitor(self.0.lock().unwrap());
106 event.record(&mut visitor);
107 }
108
record_follows_from(&self, span: &Id, follows: &Id)109 fn record_follows_from(&self, span: &Id, follows: &Id) {
110 let _ = (span, follows);
111 }
112
enabled(&self, metadata: &Metadata<'_>) -> bool113 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
114 let _ = metadata;
115 true
116 }
117
enter(&self, span: &Id)118 fn enter(&self, span: &Id) {
119 let _ = span;
120 }
121
exit(&self, span: &Id)122 fn exit(&self, span: &Id) {
123 let _ = span;
124 }
125 }
126
127 /// A subscriber that is enabled but otherwise does nothing.
128 struct EnabledSubscriber;
129
130 impl tracing::Subscriber for EnabledSubscriber {
new_span(&self, span: &span::Attributes<'_>) -> Id131 fn new_span(&self, span: &span::Attributes<'_>) -> Id {
132 let _ = span;
133 Id::from_u64(0xDEAD_FACE)
134 }
135
event(&self, event: &Event<'_>)136 fn event(&self, event: &Event<'_>) {
137 let _ = event;
138 }
139
record(&self, span: &Id, values: &span::Record<'_>)140 fn record(&self, span: &Id, values: &span::Record<'_>) {
141 let _ = (span, values);
142 }
143
record_follows_from(&self, span: &Id, follows: &Id)144 fn record_follows_from(&self, span: &Id, follows: &Id) {
145 let _ = (span, follows);
146 }
147
enabled(&self, metadata: &Metadata<'_>) -> bool148 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
149 let _ = metadata;
150 true
151 }
152
enter(&self, span: &Id)153 fn enter(&self, span: &Id) {
154 let _ = span;
155 }
156
exit(&self, span: &Id)157 fn exit(&self, span: &Id) {
158 let _ = span;
159 }
160 }
161