Skip to content

Commit 2bf05f6

Browse files
authored
perf: More Context benchmarks (#2707)
1 parent 7954252 commit 2bf05f6

File tree

3 files changed

+166
-9
lines changed

3 files changed

+166
-9
lines changed

opentelemetry-sdk/benches/context.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
1+
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
22
use opentelemetry::{
33
global::BoxedTracer,
44
trace::{
@@ -30,27 +30,57 @@ fn criterion_benchmark(c: &mut Criterion) {
3030
group.bench_function(
3131
BenchmarkId::new("has_active_span", param.clone()),
3232
|b| match api {
33-
Api::Alt => b.iter(|| Context::map_current(TraceContextExt::has_active_span)),
34-
Api::Spec => b.iter(|| Context::current().has_active_span()),
33+
Api::Alt => b.iter(has_active_span_alt),
34+
Api::Spec => b.iter(has_active_span_spec),
3535
},
3636
);
3737
group.bench_function(
3838
BenchmarkId::new("is_sampled", param.clone()),
3939
|b| match api {
40-
Api::Alt => {
41-
b.iter(|| Context::map_current(|cx| cx.span().span_context().is_sampled()))
42-
}
43-
Api::Spec => b.iter(|| Context::current().span().span_context().is_sampled()),
40+
Api::Alt => b.iter(is_sampled_alt),
41+
Api::Spec => b.iter(is_sampled_spec),
4442
},
4543
);
4644
group.bench_function(BenchmarkId::new("is_recording", param), |b| match api {
47-
Api::Alt => b.iter(|| Context::map_current(|cx| cx.span().is_recording())),
48-
Api::Spec => b.iter(|| Context::current().span().is_recording()),
45+
Api::Alt => b.iter(is_recording_alt),
46+
Api::Spec => b.iter(is_recording_spec),
4947
});
5048
}
5149
}
5250
}
5351

52+
#[inline(never)]
53+
fn has_active_span_alt() {
54+
let _ = black_box(Context::map_current(TraceContextExt::has_active_span));
55+
}
56+
57+
#[inline(never)]
58+
fn has_active_span_spec() {
59+
let _ = black_box(Context::current().has_active_span());
60+
}
61+
62+
#[inline(never)]
63+
fn is_sampled_alt() {
64+
let _ = black_box(Context::map_current(|cx| {
65+
cx.span().span_context().is_sampled()
66+
}));
67+
}
68+
69+
#[inline(never)]
70+
fn is_sampled_spec() {
71+
let _ = black_box(Context::current().span().span_context().is_sampled());
72+
}
73+
74+
#[inline(never)]
75+
fn is_recording_alt() {
76+
let _ = black_box(Context::map_current(|cx| cx.span().is_recording()));
77+
}
78+
79+
#[inline(never)]
80+
fn is_recording_spec() {
81+
let _ = black_box(Context::current().span().is_recording());
82+
}
83+
5484
#[derive(Copy, Clone)]
5585
enum Api {
5686
/// An alternative way which may be faster than what the spec recommends.

opentelemetry/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ harness = false
5757
name = "anyvalue"
5858
harness = false
5959

60+
[[bench]]
61+
name = "context_attach"
62+
harness = false
63+
required-features = ["tracing"]
64+
6065
[lib]
6166
bench = false
6267

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use criterion::{
2+
black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
3+
Criterion, Throughput,
4+
};
5+
use opentelemetry::{
6+
trace::{SpanContext, TraceContextExt},
7+
Context,
8+
};
9+
10+
// Run this benchmark with:
11+
// cargo bench --bench current_context
12+
13+
fn criterion_benchmark(c: &mut Criterion) {
14+
let span_context = Context::new().with_remote_span_context(SpanContext::empty_context());
15+
let contexts = vec![
16+
("empty_cx", Context::new()),
17+
("single_value_cx", Context::new().with_value(Value(4711))),
18+
("span_cx", span_context),
19+
];
20+
for (name, cx) in contexts {
21+
single_cx_scope(&mut group(c), name, &cx);
22+
nested_cx_scope(&mut group(c), name, &cx);
23+
overlapping_cx_scope(&mut group(c), name, &cx);
24+
}
25+
}
26+
27+
fn single_cx_scope(
28+
group: &mut BenchmarkGroup<'_, WallTime>,
29+
context_type: &str,
30+
context: &Context,
31+
) {
32+
let _restore = Context::current().attach();
33+
group.throughput(Throughput::Elements(1)).bench_function(
34+
BenchmarkId::new("single_cx_scope", context_type),
35+
|b| {
36+
b.iter_batched(
37+
|| context.clone(),
38+
|cx| {
39+
single_cx(cx);
40+
},
41+
criterion::BatchSize::SmallInput,
42+
);
43+
},
44+
);
45+
}
46+
47+
#[inline(never)]
48+
fn single_cx(cx: Context) {
49+
let cx = black_box(cx.attach());
50+
let _ = black_box(dummy_work());
51+
drop(cx);
52+
}
53+
54+
fn nested_cx_scope(group: &mut BenchmarkGroup<'_, WallTime>, cx_type: &str, context: &Context) {
55+
let _restore = Context::current().attach();
56+
group.throughput(Throughput::Elements(1)).bench_function(
57+
BenchmarkId::new("nested_cx_scope", cx_type),
58+
|b| {
59+
b.iter_batched(
60+
|| (context.clone(), context.clone()),
61+
|(cx1, cx2)| {
62+
nested_cx(cx1, cx2);
63+
},
64+
criterion::BatchSize::SmallInput,
65+
);
66+
},
67+
);
68+
}
69+
70+
#[inline(never)]
71+
fn nested_cx(cx1: Context, cx2: Context) {
72+
let outer = black_box(cx1.attach());
73+
let inner = black_box(cx2.attach());
74+
let _ = black_box(dummy_work());
75+
drop(inner);
76+
drop(outer);
77+
}
78+
79+
fn overlapping_cx_scope(
80+
group: &mut BenchmarkGroup<'_, WallTime>,
81+
cx_type: &str,
82+
context: &Context,
83+
) {
84+
let _restore = Context::current().attach();
85+
group.throughput(Throughput::Elements(1)).bench_function(
86+
BenchmarkId::new("overlapping_cx_scope", cx_type),
87+
|b| {
88+
b.iter_batched(
89+
|| (context.clone(), context.clone()),
90+
|(cx1, cx2)| {
91+
overlapping_cx(cx1, cx2);
92+
},
93+
criterion::BatchSize::SmallInput,
94+
);
95+
},
96+
);
97+
}
98+
99+
#[inline(never)]
100+
fn overlapping_cx(cx1: Context, cx2: Context) {
101+
let outer = cx1.attach();
102+
let inner = cx2.attach();
103+
let _ = black_box(dummy_work());
104+
drop(outer);
105+
drop(inner);
106+
}
107+
108+
#[inline(never)]
109+
fn dummy_work() -> i32 {
110+
black_box(1 + 1)
111+
}
112+
113+
fn group(c: &mut Criterion) -> BenchmarkGroup<WallTime> {
114+
c.benchmark_group("context_attach")
115+
}
116+
117+
#[derive(Debug, PartialEq)]
118+
struct Value(i32);
119+
120+
criterion_group!(benches, criterion_benchmark);
121+
122+
criterion_main!(benches);

0 commit comments

Comments
 (0)