Skip to content

Improve cost of creating AttributeSets #1379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Nov 22, 2023
47 changes: 24 additions & 23 deletions opentelemetry-sdk/src/attributes/set.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;
use std::{
cmp::Ordering,
collections::{BTreeSet, HashSet},
hash::{Hash, Hasher},
};

Expand Down Expand Up @@ -105,36 +105,37 @@ impl Eq for HashKeyValue {}
/// This must implement [Hash], [PartialEq], and [Eq] so it may be used as
/// HashMap keys and other de-duplication methods.
#[derive(Clone, Default, Debug, Hash, PartialEq, Eq)]
pub struct AttributeSet(BTreeSet<HashKeyValue>);
pub struct AttributeSet(Vec<HashKeyValue>);

impl From<&[KeyValue]> for AttributeSet {
fn from(values: &[KeyValue]) -> Self {
let mut seen = HashSet::with_capacity(values.len());
AttributeSet(
values
.iter()
.rev()
.filter_map(|kv| {
if seen.contains(&&kv.key) {
None
} else {
seen.insert(&kv.key);
Some(HashKeyValue(kv.clone()))
}
})
.collect(),
)
let mut seen_keys = HashSet::with_capacity(values.len());
let mut vec = values
.iter()
.rev()
.filter_map(|kv| {
if seen_keys.insert(kv.key.clone()) {
Some(HashKeyValue(kv.clone()))
} else {
None
}
})
.collect::<Vec<_>>();
vec.sort_unstable();

AttributeSet(vec)
}
}

impl From<&Resource> for AttributeSet {
fn from(values: &Resource) -> Self {
AttributeSet(
values
.iter()
.map(|(key, value)| HashKeyValue(KeyValue::new(key.clone(), value.clone())))
.collect(),
)
let mut vec = values
.iter()
.map(|(key, value)| HashKeyValue(KeyValue::new(key.clone(), value.clone())))
.collect::<Vec<_>>();
vec.sort_unstable();

AttributeSet(vec)
}
}

Expand Down