Skip to content

Commit d58b454

Browse files
committed
perf(sdk): add optional foldhash for ValueMap HashMaps in metrics hot path
1 parent dba1820 commit d58b454

3 files changed

Lines changed: 23 additions & 3 deletions

File tree

opentelemetry-sdk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## vNext
44

5+
- Add optional `metrics-use-foldhash` feature flag to use [foldhash](https://github.com/orlp/foldhash) for `ValueMap` HashMaps in the metrics hot path, providing ~30% improvement over the default std `SipHash` hasher. [#3388](https://github.com/open-telemetry/opentelemetry-rust/pull/3388)
56
- Add 32-bit platform support by using `portable-atomic` for `AtomicI64` and `AtomicU64` in the metrics module. This enables compilation on 32-bit ARM targets (e.g., `armv5te-unknown-linux-gnueabi`, `armv7-unknown-linux-gnueabihf`).
67
- `Aggregation` enum and `StreamBuilder::with_aggregation()` are now stable and no longer require the `spec_unstable_metrics_views` feature flag.
78
- Fix `service.name` Resource attribute fallback to follow OpenTelemetry

opentelemetry-sdk/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ autobenches = false
1212

1313
[dependencies]
1414
opentelemetry = { workspace = true }
15+
foldhash = { version = "0.1", optional = true }
1516
opentelemetry-http = { workspace = true, optional = true }
1617
futures-channel = { workspace = true }
1718
futures-executor = { workspace = true }
@@ -59,6 +60,7 @@ experimental_logs_batch_log_processor_with_async_runtime = ["logs", "experimenta
5960
experimental_logs_concurrent_log_processor = ["logs"]
6061
experimental_trace_batch_span_processor_with_async_runtime = ["tokio/sync", "trace", "experimental_async_runtime"]
6162
experimental_metrics_disable_name_validation = ["metrics"]
63+
metrics-use-foldhash = ["metrics", "foldhash"]
6264
bench_profiling = []
6365

6466
[[bench]]

opentelemetry-sdk/src/metrics/internal/mod.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::fmt;
99
#[cfg(not(target_has_atomic = "64"))]
1010
use portable_atomic::{AtomicI64, AtomicU64};
1111
use std::cmp::min;
12-
use std::collections::{HashMap, HashSet};
12+
use std::collections::HashSet;
1313
use std::mem::swap;
1414
use std::ops::{Add, AddAssign, DerefMut, Sub};
1515
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
@@ -24,6 +24,23 @@ use opentelemetry::{otel_warn, KeyValue};
2424
use super::data::{AggregatedMetrics, MetricData};
2525
use super::pipeline::DEFAULT_CARDINALITY_LIMIT;
2626

27+
#[cfg(feature = "metrics-use-foldhash")]
28+
type HashMap<K, V> = std::collections::HashMap<K, V, foldhash::fast::RandomState>;
29+
#[cfg(not(feature = "metrics-use-foldhash"))]
30+
type HashMap<K, V> = std::collections::HashMap<K, V>;
31+
32+
#[cfg(feature = "metrics-use-foldhash")]
33+
fn new_hashmap<K, V>(capacity: usize) -> HashMap<K, V> {
34+
std::collections::HashMap::with_capacity_and_hasher(
35+
capacity,
36+
foldhash::fast::RandomState::default(),
37+
)
38+
}
39+
#[cfg(not(feature = "metrics-use-foldhash"))]
40+
fn new_hashmap<K, V>(capacity: usize) -> HashMap<K, V> {
41+
std::collections::HashMap::with_capacity(capacity)
42+
}
43+
2744
// TODO Replace it with LazyLock once it is stable
2845
pub(crate) static STREAM_OVERFLOW_ATTRIBUTES: OnceLock<Vec<KeyValue>> = OnceLock::new();
2946

@@ -85,7 +102,7 @@ where
85102
{
86103
fn new(config: A::InitConfig, cardinality_limit: usize) -> Self {
87104
ValueMap {
88-
trackers: RwLock::new(HashMap::with_capacity(
105+
trackers: RwLock::new(new_hashmap(
89106
1 + min(DEFAULT_CARDINALITY_LIMIT, cardinality_limit),
90107
)),
91108
trackers_for_collect: OnceLock::new(),
@@ -100,7 +117,7 @@ where
100117
#[inline]
101118
fn trackers_for_collect(&self) -> &RwLock<HashMap<Vec<KeyValue>, Arc<A>>> {
102119
self.trackers_for_collect.get_or_init(|| {
103-
RwLock::new(HashMap::with_capacity(
120+
RwLock::new(new_hashmap(
104121
1 + min(DEFAULT_CARDINALITY_LIMIT, self.cardinality_limit),
105122
))
106123
})

0 commit comments

Comments
 (0)