• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use criterion::{criterion_group, criterion_main, Criterion};
2 use std::{
3     thread::{self, JoinHandle},
4     time::Instant,
5 };
6 use tracing::{event, Level};
7 use tracing_appender::non_blocking;
8 use tracing_subscriber::fmt::MakeWriter;
9 
10 // a no-op writer is used in order to measure the overhead incurred by
11 // tracing-subscriber.
12 #[derive(Clone)]
13 struct NoOpWriter;
14 
15 impl NoOpWriter {
new() -> NoOpWriter16     fn new() -> NoOpWriter {
17         NoOpWriter
18     }
19 }
20 
21 impl<'a> MakeWriter<'a> for NoOpWriter {
22     type Writer = NoOpWriter;
23 
make_writer(&self) -> Self::Writer24     fn make_writer(&self) -> Self::Writer {
25         self.clone()
26     }
27 }
28 
29 impl std::io::Write for NoOpWriter {
write(&mut self, buf: &[u8]) -> std::io::Result<usize>30     fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
31         Ok(buf.len())
32     }
33 
flush(&mut self) -> std::io::Result<()>34     fn flush(&mut self) -> std::io::Result<()> {
35         Ok(())
36     }
37 }
38 
synchronous_benchmark(c: &mut Criterion)39 fn synchronous_benchmark(c: &mut Criterion) {
40     let mut group = c.benchmark_group("synchronous");
41     group.bench_function("single_thread", |b| {
42         let subscriber = tracing_subscriber::fmt().with_writer(NoOpWriter::new());
43         tracing::subscriber::with_default(subscriber.finish(), || {
44             b.iter(|| event!(Level::INFO, "event"))
45         });
46     });
47 
48     group.bench_function("multiple_writers", |b| {
49         b.iter_custom(|iters| {
50             let mut handles: Vec<JoinHandle<()>> = Vec::new();
51 
52             let start = Instant::now();
53 
54             let make_writer = NoOpWriter::new();
55             let cloned_make_writer = make_writer.clone();
56 
57             handles.push(thread::spawn(move || {
58                 let subscriber = tracing_subscriber::fmt().with_writer(make_writer);
59                 tracing::subscriber::with_default(subscriber.finish(), || {
60                     for _ in 0..iters {
61                         event!(Level::INFO, "event");
62                     }
63                 });
64             }));
65 
66             handles.push(thread::spawn(move || {
67                 let subscriber = tracing_subscriber::fmt().with_writer(cloned_make_writer);
68                 tracing::subscriber::with_default(subscriber.finish(), || {
69                     for _ in 0..iters {
70                         event!(Level::INFO, "event");
71                     }
72                 });
73             }));
74 
75             for handle in handles {
76                 let _ = handle.join();
77             }
78 
79             start.elapsed()
80         });
81     });
82 }
83 
non_blocking_benchmark(c: &mut Criterion)84 fn non_blocking_benchmark(c: &mut Criterion) {
85     let mut group = c.benchmark_group("non_blocking");
86 
87     group.bench_function("single_thread", |b| {
88         let (non_blocking, _guard) = non_blocking(NoOpWriter::new());
89         let subscriber = tracing_subscriber::fmt().with_writer(non_blocking);
90 
91         tracing::subscriber::with_default(subscriber.finish(), || {
92             b.iter(|| event!(Level::INFO, "event"))
93         });
94     });
95 
96     group.bench_function("multiple_writers", |b| {
97         b.iter_custom(|iters| {
98             let (non_blocking, _guard) = non_blocking(NoOpWriter::new());
99 
100             let mut handles: Vec<JoinHandle<()>> = Vec::new();
101 
102             let start = Instant::now();
103 
104             let cloned_make_writer = non_blocking.clone();
105 
106             handles.push(thread::spawn(move || {
107                 let subscriber = tracing_subscriber::fmt().with_writer(non_blocking);
108                 tracing::subscriber::with_default(subscriber.finish(), || {
109                     for _ in 0..iters {
110                         event!(Level::INFO, "event");
111                     }
112                 });
113             }));
114 
115             handles.push(thread::spawn(move || {
116                 let subscriber = tracing_subscriber::fmt().with_writer(cloned_make_writer);
117                 tracing::subscriber::with_default(subscriber.finish(), || {
118                     for _ in 0..iters {
119                         event!(Level::INFO, "event");
120                     }
121                 });
122             }));
123 
124             for handle in handles {
125                 let _ = handle.join();
126             }
127 
128             start.elapsed()
129         });
130     });
131 }
132 
133 criterion_group!(benches, synchronous_benchmark, non_blocking_benchmark);
134 criterion_main!(benches);
135