260 lines
9.4 KiB
Rust
260 lines
9.4 KiB
Rust
/*
|
|
The benchmark results:
|
|
criterion = "0.5.1"
|
|
rustc 1.83.0 (90b35a623 2024-11-26)
|
|
OS: Ubuntu 22.04.4 LTS (5.15.167.4-microsoft-standard-WSL2)
|
|
Hardware: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz 2.79 GHz
|
|
RAM: 64.0 GB
|
|
| Test | Average time|
|
|
|-------------------------------------------------------|-------------|
|
|
| Counter_Add_Sorted | 160 ns |
|
|
| Counter_Add_Unsorted | 164 ns |
|
|
| Counter_Add_Sorted_With_Non_Static_Values | 238 ns |
|
|
| Counter_Overflow | 562 ns |
|
|
| ThreadLocal_Random_Generator_5 | 37 ns |
|
|
*/
|
|
|
|
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
|
use opentelemetry::{
|
|
metrics::{Counter, MeterProvider as _},
|
|
KeyValue,
|
|
};
|
|
use opentelemetry_sdk::metrics::{ManualReader, SdkMeterProvider};
|
|
#[cfg(all(not(target_os = "windows"), feature = "bench_profiling"))]
|
|
use pprof::criterion::{Output, PProfProfiler};
|
|
use rand::{
|
|
rngs::{self},
|
|
Rng, SeedableRng,
|
|
};
|
|
use std::cell::RefCell;
|
|
|
|
thread_local! {
|
|
/// Store random number generator for each thread
|
|
static CURRENT_RNG: RefCell<rngs::SmallRng> = RefCell::new(rngs::SmallRng::from_os_rng());
|
|
}
|
|
|
|
static ATTRIBUTE_VALUES: [&str; 10] = [
|
|
"value1", "value2", "value3", "value4", "value5", "value6", "value7", "value8", "value9",
|
|
"value10",
|
|
];
|
|
|
|
// Run this benchmark with:
|
|
// cargo bench --bench metrics_counter
|
|
fn create_counter(name: &'static str) -> Counter<u64> {
|
|
let meter_provider: SdkMeterProvider = SdkMeterProvider::builder()
|
|
.with_reader(ManualReader::builder().build())
|
|
.build();
|
|
let meter = meter_provider.meter("benchmarks");
|
|
|
|
println!("Counter_Created");
|
|
meter.u64_counter(name).build()
|
|
}
|
|
|
|
fn criterion_benchmark(c: &mut Criterion) {
|
|
counter_add_sorted(c);
|
|
counter_add_unsorted(c);
|
|
|
|
let attribute_values: [String; 10] = (1..=10)
|
|
.map(|i| format!("value{i}"))
|
|
.collect::<Vec<String>>()
|
|
.try_into()
|
|
.expect("Expected a Vec of length 10");
|
|
|
|
counter_add_sorted_with_non_static_values(c, attribute_values);
|
|
|
|
counter_overflow(c);
|
|
random_generator(c);
|
|
}
|
|
|
|
fn counter_add_sorted(c: &mut Criterion) {
|
|
let counter = create_counter("Counter_Add_Sorted");
|
|
c.bench_function("Counter_Add_Sorted", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
// 4*4*10*10 = 1600 time series.
|
|
CURRENT_RNG.with(|rng| {
|
|
let mut rng = rng.borrow_mut();
|
|
[
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
]
|
|
})
|
|
},
|
|
|rands| {
|
|
let index_first_attribute = rands[0];
|
|
let index_second_attribute = rands[1];
|
|
let index_third_attribute = rands[2];
|
|
let index_fourth_attribute = rands[3];
|
|
counter.add(
|
|
1,
|
|
&[
|
|
KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]),
|
|
KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]),
|
|
KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]),
|
|
KeyValue::new("attribute4", ATTRIBUTE_VALUES[index_fourth_attribute]),
|
|
],
|
|
);
|
|
},
|
|
BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
|
|
fn counter_add_unsorted(c: &mut Criterion) {
|
|
let counter = create_counter("Counter_Add_Unsorted");
|
|
c.bench_function("Counter_Add_Unsorted", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
// 4*4*10*10 = 1600 time series.
|
|
CURRENT_RNG.with(|rng| {
|
|
let mut rng = rng.borrow_mut();
|
|
[
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
]
|
|
})
|
|
},
|
|
|rands| {
|
|
let index_first_attribute = rands[0];
|
|
let index_second_attribute = rands[1];
|
|
let index_third_attribute = rands[2];
|
|
let index_fourth_attribute = rands[3];
|
|
counter.add(
|
|
1,
|
|
&[
|
|
KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]),
|
|
KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]),
|
|
KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]),
|
|
KeyValue::new("attribute4", ATTRIBUTE_VALUES[index_fourth_attribute]),
|
|
],
|
|
);
|
|
},
|
|
BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
|
|
fn counter_add_sorted_with_non_static_values(c: &mut Criterion, attribute_values: [String; 10]) {
|
|
let counter = create_counter("Counter_Add_Sorted_With_Non_Static_Values");
|
|
c.bench_function("Counter_Add_Sorted_With_Non_Static_Values", |b| {
|
|
b.iter_batched(
|
|
|| {
|
|
// 4*4*10*10 = 1600 time series.
|
|
CURRENT_RNG.with(|rng| {
|
|
let mut rng = rng.borrow_mut();
|
|
[
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
]
|
|
})
|
|
},
|
|
|rands| {
|
|
let index_first_attribute = rands[0];
|
|
let index_second_attribute = rands[1];
|
|
let index_third_attribute = rands[2];
|
|
let index_fourth_attribute = rands[3];
|
|
counter.add(
|
|
1,
|
|
&[
|
|
KeyValue::new(
|
|
"attribute1",
|
|
attribute_values[index_first_attribute].as_str().to_owned(),
|
|
),
|
|
KeyValue::new(
|
|
"attribute2",
|
|
attribute_values[index_second_attribute].as_str().to_owned(),
|
|
),
|
|
KeyValue::new(
|
|
"attribute3",
|
|
attribute_values[index_third_attribute].as_str().to_owned(),
|
|
),
|
|
KeyValue::new(
|
|
"attribute4",
|
|
attribute_values[index_fourth_attribute].as_str().to_owned(),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
|
|
fn counter_overflow(c: &mut Criterion) {
|
|
let counter = create_counter("Counter_Overflow");
|
|
// Cause overflow.
|
|
for v in 0..2001 {
|
|
counter.add(100, &[KeyValue::new("A", v.to_string())]);
|
|
}
|
|
|
|
c.bench_function("Counter_Overflow", |b| {
|
|
b.iter(|| {
|
|
// 4*4*10*10 = 1600 time series.
|
|
let rands = CURRENT_RNG.with(|rng| {
|
|
let mut rng = rng.borrow_mut();
|
|
[
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
]
|
|
});
|
|
let index_first_attribute = rands[0];
|
|
let index_second_attribute = rands[1];
|
|
let index_third_attribute = rands[2];
|
|
let index_fourth_attribute = rands[3];
|
|
counter.add(
|
|
1,
|
|
&[
|
|
KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]),
|
|
KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]),
|
|
KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]),
|
|
KeyValue::new("attribute4", ATTRIBUTE_VALUES[index_fourth_attribute]),
|
|
],
|
|
);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn random_generator(c: &mut Criterion) {
|
|
c.bench_function("ThreadLocal_Random_Generator_5", |b| {
|
|
b.iter(|| {
|
|
let __i1 = CURRENT_RNG.with(|rng| {
|
|
let mut rng = rng.borrow_mut();
|
|
[
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..4),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
rng.random_range(0..10),
|
|
]
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
#[cfg(all(not(target_os = "windows"), feature = "bench_profiling"))]
|
|
criterion_group! {
|
|
name = benches;
|
|
config = Criterion::default()
|
|
.warm_up_time(std::time::Duration::from_secs(1))
|
|
.measurement_time(std::time::Duration::from_secs(2))
|
|
.with_profiler(PProfProfiler::new(100, Output::Flamegraph(None)));
|
|
targets = criterion_benchmark
|
|
}
|
|
#[cfg(any(target_os = "windows", not(feature = "bench_profiling")))]
|
|
criterion_group! {
|
|
name = benches;
|
|
config = Criterion::default()
|
|
.warm_up_time(std::time::Duration::from_secs(1))
|
|
.measurement_time(std::time::Duration::from_secs(2));
|
|
targets = criterion_benchmark
|
|
}
|
|
criterion_main!(benches);
|