Skip to content

Commit 61ff426

Browse files
authored
perf: Add trace and logs API benchmarks to opentelemetry crate (#3476)
1 parent 6ec878f commit 61ff426

5 files changed

Lines changed: 300 additions & 8 deletions

File tree

opentelemetry/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ required-features = ["tracing"]
6868
name = "context_suppression"
6969
harness = false
7070

71+
[[bench]]
72+
name = "trace"
73+
harness = false
74+
required-features = ["trace"]
75+
76+
[[bench]]
77+
name = "logs"
78+
harness = false
79+
required-features = ["logs"]
80+
7181
[[bench]]
7282
name = "baggage"
7383
harness = false

opentelemetry/benches/attributes.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ RAM: 64.0 GB
1212
| CreateOtelKeyValueArrayWithMixedValueTypes | 18.1 ns |
1313
| CreateOtelKeyValueArrayWithNonStaticValues | 90.1 ns |
1414
| CreateTupleKeyValueArray | 2.73 ns |
15+
16+
OS: macOS 15
17+
Hardware: Apple M4 Pro, 14 cores, RAM: 24 GB
18+
| Test | Average time|
19+
|--------------------------------------------------|-------------|
20+
| CreateOTelKey_Static | 0.28 ns |
21+
| CreateOTelKey_Owned | 19.16 ns |
22+
| CreateOTelKey_Arc | 21.76 ns |
23+
| CreateOTelKeyValue | 1.30 ns |
24+
| CreateTupleKeyValue | 0.26 ns |
25+
| CreateOtelKeyValueArray | 7.41 ns |
26+
| CreateOtelKeyValueArrayWithMixedValueTypes | 5.50 ns |
27+
| CreateOtelKeyValueArrayWithNonStaticValues | 84.94 ns |
28+
| CreateTupleKeyValueArray | 1.46 ns |
1529
*/
1630

1731
use criterion::{criterion_group, criterion_main, Criterion};

opentelemetry/benches/logs.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
Benchmark Results:
3+
criterion = "0.5.1"
4+
OS: macOS 15
5+
Hardware: Apple M4 Pro, 14 cores, RAM: 24 GB
6+
| Test | Average time|
7+
|--------------------------------------------------|-------------|
8+
| CreateLogRecord_NoopLogger | 0.26 ns |
9+
| CreateLogRecord_NoopLogger_WithAttributes | 0.26 ns |
10+
| CreateLogRecord_NoopLogger_WithBody | 1.30 ns |
11+
| CreateLogRecord_NoopLogger_Full | 1.30 ns |
12+
| EventEnabled_NoopLogger | 0.26 ns |
13+
*/
14+
15+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
16+
use opentelemetry::logs::{
17+
AnyValue, LogRecord, Logger, LoggerProvider, NoopLoggerProvider, Severity,
18+
};
19+
20+
// Run this benchmark with:
21+
// cargo bench --bench logs --features=logs
22+
23+
fn criterion_benchmark(c: &mut Criterion) {
24+
let provider = NoopLoggerProvider::new();
25+
let logger = provider.logger("bench");
26+
27+
c.bench_function("CreateLogRecord_NoopLogger", |b| {
28+
b.iter(|| {
29+
let record = logger.create_log_record();
30+
logger.emit(record);
31+
});
32+
});
33+
34+
c.bench_function("CreateLogRecord_NoopLogger_WithAttributes", |b| {
35+
b.iter(|| {
36+
let mut record = logger.create_log_record();
37+
record.add_attribute("key1", "value1");
38+
record.add_attribute("key2", 123);
39+
record.add_attribute("key3", true);
40+
record.add_attribute("key4", 123.456);
41+
logger.emit(record);
42+
});
43+
});
44+
45+
c.bench_function("CreateLogRecord_NoopLogger_WithBody", |b| {
46+
b.iter(|| {
47+
let mut record = logger.create_log_record();
48+
record.set_body(AnyValue::String("This is a log message".into()));
49+
record.set_severity_number(Severity::Info);
50+
record.set_severity_text("INFO");
51+
logger.emit(record);
52+
});
53+
});
54+
55+
c.bench_function("CreateLogRecord_NoopLogger_Full", |b| {
56+
b.iter(|| {
57+
let mut record = logger.create_log_record();
58+
record.set_body(AnyValue::String("This is a log message".into()));
59+
record.set_severity_number(Severity::Warn);
60+
record.set_severity_text("WARN");
61+
record.set_event_name("my.event");
62+
record.set_target("my_crate::my_module");
63+
record.add_attribute("key1", "value1");
64+
record.add_attribute("key2", 123);
65+
record.add_attribute("key3", true);
66+
record.add_attribute("key4", 123.456);
67+
logger.emit(record);
68+
});
69+
});
70+
71+
c.bench_function("EventEnabled_NoopLogger", |b| {
72+
b.iter(|| {
73+
black_box(logger.event_enabled(Severity::Info, "my_target", Some("my_event")));
74+
});
75+
});
76+
}
77+
78+
criterion_group! {
79+
name = benches;
80+
config = Criterion::default()
81+
.warm_up_time(std::time::Duration::from_secs(1))
82+
.measurement_time(std::time::Duration::from_secs(2));
83+
targets = criterion_benchmark
84+
}
85+
criterion_main!(benches);

opentelemetry/benches/metrics.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
/*
22
Benchmark Results:
33
criterion = "0.5.1"
4-
OS: Ubuntu 22.04.4 LTS (5.15.153.1-microsoft-standard-WSL2)
5-
Hardware: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz, 16vCPUs,
6-
RAM: 64.0 GB
4+
OS: macOS 15
5+
Hardware: Apple M4 Pro, 14 cores, RAM: 24 GB
76
| Test | Average time|
87
|-----------------------------------------------------|-------------|
9-
| NoAttributes | 1.1616 ns |
10-
| AddWithInlineStaticAttributes | 13.296 ns |
11-
| AddWithStaticArray | 1.1612 ns |
12-
| AddWithDynamicAttributes | 110.40 ns |
13-
| AddWithDynamicAttributes_WithStringAllocation | 77.338 ns |
8+
| NoAttributes | 0.77 ns |
9+
| AddWithInlineStaticAttributes | 8.10 ns |
10+
| AddWithStaticArray | 0.77 ns |
11+
| AddWithDynamicAttributes | 44.84 ns |
12+
| AddWithDynamicAttributes_WithStringAllocation | 85.92 ns |
1413
*/
1514

1615
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};

opentelemetry/benches/trace.rs

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
Benchmark Results:
3+
criterion = "0.5.1"
4+
OS: macOS 15
5+
Hardware: Apple M4 Pro, 14 cores, RAM: 24 GB
6+
| Test | Average time|
7+
|--------------------------------------------------|-------------|
8+
| CreateSpan_NoopTracer | 29.2 ns |
9+
| CreateSpan_NoopTracer_4Attributes | 29.4 ns |
10+
| CreateSpan_NoopTracer_AddEvent | 29.2 ns |
11+
| CreateSpan_NoopTracer_AddLink | 29.2 ns |
12+
| CreateSpan_NoopTracer_SetActive | 73.3 ns |
13+
| CreateSpan_NoopTracer_WithActiveParent | 102.9 ns |
14+
| CreateSpan_NoopTracer_InSpan | 78.0 ns |
15+
| SpanBuilder_Creation | 22.8 ns |
16+
| SpanBuilder_WithAttributes | 51.7 ns |
17+
| SpanBuilder_WithLinks | 69.0 ns |
18+
*/
19+
20+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
21+
use opentelemetry::{
22+
global,
23+
trace::{
24+
noop::NoopTracerProvider, Span, SpanContext, SpanId, SpanKind, TraceFlags, TraceId,
25+
TraceState, Tracer,
26+
},
27+
KeyValue,
28+
};
29+
30+
// Run this benchmark with:
31+
// cargo bench --bench trace --features=trace
32+
33+
fn valid_span_context() -> SpanContext {
34+
SpanContext::new(
35+
TraceId::from(12345u128),
36+
SpanId::from(12345u64),
37+
TraceFlags::SAMPLED,
38+
true,
39+
TraceState::default(),
40+
)
41+
}
42+
43+
fn criterion_benchmark(c: &mut Criterion) {
44+
global::set_tracer_provider(NoopTracerProvider::new());
45+
let tracer = global::tracer("bench");
46+
47+
span_lifecycle(c, &tracer);
48+
span_builder(c, &tracer);
49+
}
50+
51+
fn span_lifecycle(
52+
c: &mut Criterion,
53+
tracer: &impl Tracer<Span = impl Span + Send + Sync + 'static>,
54+
) {
55+
c.bench_function("CreateSpan_NoopTracer", |b| {
56+
b.iter(|| {
57+
let mut span = tracer.start("test-span");
58+
span.end();
59+
});
60+
});
61+
62+
c.bench_function("CreateSpan_NoopTracer_4Attributes", |b| {
63+
b.iter(|| {
64+
let mut span = tracer.start("test-span");
65+
if span.is_recording() {
66+
span.set_attribute(KeyValue::new("key1", false));
67+
span.set_attribute(KeyValue::new("key2", "hello"));
68+
span.set_attribute(KeyValue::new("key3", 123));
69+
span.set_attribute(KeyValue::new("key4", 123.456));
70+
}
71+
span.end();
72+
});
73+
});
74+
75+
c.bench_function("CreateSpan_NoopTracer_AddEvent", |b| {
76+
b.iter(|| {
77+
let mut span = tracer.start("test-span");
78+
if span.is_recording() {
79+
span.add_event(
80+
"my-event",
81+
vec![
82+
KeyValue::new("key1", "value1"),
83+
KeyValue::new("key2", "value2"),
84+
],
85+
);
86+
}
87+
span.end();
88+
});
89+
});
90+
91+
c.bench_function("CreateSpan_NoopTracer_AddLink", |b| {
92+
let link_context = valid_span_context();
93+
b.iter(|| {
94+
let mut span = tracer.start("test-span");
95+
if span.is_recording() {
96+
span.add_link(
97+
link_context.clone(),
98+
vec![
99+
KeyValue::new("key1", "value1"),
100+
KeyValue::new("key2", "value2"),
101+
],
102+
);
103+
}
104+
span.end();
105+
});
106+
});
107+
108+
c.bench_function("CreateSpan_NoopTracer_SetActive", |b| {
109+
b.iter(|| {
110+
let span = tracer.start("test-span");
111+
let _guard = opentelemetry::trace::mark_span_as_active(span);
112+
});
113+
});
114+
115+
c.bench_function("CreateSpan_NoopTracer_WithActiveParent", |b| {
116+
b.iter(|| {
117+
let parent = tracer.start("parent");
118+
let _guard = opentelemetry::trace::mark_span_as_active(parent);
119+
let mut child = tracer.start("child");
120+
child.end();
121+
});
122+
});
123+
124+
c.bench_function("CreateSpan_NoopTracer_InSpan", |b| {
125+
b.iter(|| {
126+
tracer.in_span("test-span", |_cx| {});
127+
});
128+
});
129+
}
130+
131+
fn span_builder(c: &mut Criterion, tracer: &impl Tracer<Span = impl Span + Send + Sync + 'static>) {
132+
c.bench_function("SpanBuilder_Creation", |b| {
133+
b.iter(|| {
134+
let span = tracer
135+
.span_builder("test-span")
136+
.with_kind(SpanKind::Client)
137+
.start(tracer);
138+
black_box(span);
139+
});
140+
});
141+
142+
c.bench_function("SpanBuilder_WithAttributes", |b| {
143+
b.iter(|| {
144+
let span = tracer
145+
.span_builder("test-span")
146+
.with_kind(SpanKind::Client)
147+
.with_attributes(vec![
148+
KeyValue::new("key1", false),
149+
KeyValue::new("key2", "hello"),
150+
KeyValue::new("key3", 123),
151+
KeyValue::new("key4", 123.456),
152+
])
153+
.start(tracer);
154+
black_box(span);
155+
});
156+
});
157+
158+
c.bench_function("SpanBuilder_WithLinks", |b| {
159+
let link_context = valid_span_context();
160+
b.iter(|| {
161+
let span = tracer
162+
.span_builder("test-span")
163+
.with_links(vec![opentelemetry::trace::Link::new(
164+
link_context.clone(),
165+
vec![
166+
KeyValue::new("key1", "value1"),
167+
KeyValue::new("key2", "value2"),
168+
],
169+
0,
170+
)])
171+
.start(tracer);
172+
black_box(span);
173+
});
174+
});
175+
}
176+
177+
criterion_group! {
178+
name = benches;
179+
config = Criterion::default()
180+
.warm_up_time(std::time::Duration::from_secs(1))
181+
.measurement_time(std::time::Duration::from_secs(2));
182+
targets = criterion_benchmark
183+
}
184+
criterion_main!(benches);

0 commit comments

Comments
 (0)