Skip to content

Commit

Permalink
perf: Optimize cloning of Context since entries are immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
bantonsson committed Feb 28, 2025
1 parent f0d6424 commit 7725b37
Showing 1 changed file with 23 additions and 17 deletions.
40 changes: 23 additions & 17 deletions opentelemetry/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ thread_local! {
pub struct Context {
#[cfg(feature = "trace")]
pub(super) span: Option<Arc<SynchronizedSpan>>,
entries: HashMap<TypeId, Arc<dyn Any + Sync + Send>, BuildHasherDefault<IdHasher>>,
entries: Option<Arc<EntryMap>>,
}

type EntryMap = HashMap<TypeId, Arc<dyn Any + Sync + Send>, BuildHasherDefault<IdHasher>>;

impl Context {
/// Creates an empty `Context`.
///
Expand Down Expand Up @@ -111,7 +113,7 @@ impl Context {
/// do_work()
/// ```
pub fn current() -> Self {
Context::map_current(|cx| cx.clone())
Self::map_current(|cx| cx.clone())
}

/// Applies a function to the current context returning its value.
Expand Down Expand Up @@ -153,12 +155,7 @@ impl Context {
/// assert_eq!(all_current_and_b.get::<ValueB>(), Some(&ValueB(42)));
/// ```
pub fn current_with_value<T: 'static + Send + Sync>(value: T) -> Self {
let mut new_context = Context::current();
new_context
.entries
.insert(TypeId::of::<T>(), Arc::new(value));

new_context
Self::map_current(|cx| cx.with_value(value))
}

/// Returns a reference to the entry for the corresponding value type.
Expand All @@ -184,8 +181,9 @@ impl Context {
/// ```
pub fn get<T: 'static>(&self) -> Option<&T> {
self.entries
.get(&TypeId::of::<T>())
.and_then(|rc| rc.downcast_ref())
.as_ref()?
.get(&TypeId::of::<T>())?
.downcast_ref()
}

/// Returns a copy of the context with the new value included.
Expand Down Expand Up @@ -216,12 +214,20 @@ impl Context {
/// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
/// ```
pub fn with_value<T: 'static + Send + Sync>(&self, value: T) -> Self {
let mut new_context = self.clone();
new_context
.entries
.insert(TypeId::of::<T>(), Arc::new(value));

new_context
let entries = if let Some(current_entries) = &self.entries {
let mut inner_entries = (**current_entries).clone();
inner_entries.insert(TypeId::of::<T>(), Arc::new(value));
Some(Arc::new(inner_entries))
} else {
let mut entries = EntryMap::default();
entries.insert(TypeId::of::<T>(), Arc::new(value));
Some(Arc::new(entries))
};
Context {
entries,
#[cfg(feature = "trace")]
span: self.span.clone(),
}
}

/// Replaces the current context on this thread with this context.
Expand Down Expand Up @@ -327,7 +333,7 @@ impl Context {
impl fmt::Debug for Context {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut dbg = f.debug_struct("Context");
let mut entries = self.entries.len();
let mut entries = self.entries.as_ref().map_or(0, |e| e.len());
#[cfg(feature = "trace")]
{
if let Some(span) = &self.span {
Expand Down

0 comments on commit 7725b37

Please sign in to comment.