Skip to content

Commit 828ba76

Browse files
committed
Optimize cloning of Context since entries are immutable
1 parent fd8ca86 commit 828ba76

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

opentelemetry/src/context.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,11 @@ thread_local! {
7878
pub struct Context {
7979
#[cfg(feature = "trace")]
8080
pub(super) span: Option<Arc<SynchronizedSpan>>,
81-
entries: HashMap<TypeId, Arc<dyn Any + Sync + Send>, BuildHasherDefault<IdHasher>>,
81+
entries: Option<Arc<EntryMap>>,
8282
}
8383

84+
type EntryMap = HashMap<TypeId, Arc<dyn Any + Sync + Send>, BuildHasherDefault<IdHasher>>;
85+
8486
impl Context {
8587
/// Creates an empty `Context`.
8688
///
@@ -152,12 +154,7 @@ impl Context {
152154
/// assert_eq!(all_current_and_b.get::<ValueB>(), Some(&ValueB(42)));
153155
/// ```
154156
pub fn current_with_value<T: 'static + Send + Sync>(value: T) -> Self {
155-
let mut new_context = Context::current();
156-
new_context
157-
.entries
158-
.insert(TypeId::of::<T>(), Arc::new(value));
159-
160-
new_context
157+
Context::map_current(|cx| cx.with_value(value))
161158
}
162159

163160
/// Returns a reference to the entry for the corresponding value type.
@@ -182,9 +179,13 @@ impl Context {
182179
/// assert_eq!(cx.get::<MyUser>(), None);
183180
/// ```
184181
pub fn get<T: 'static>(&self) -> Option<&T> {
185-
self.entries
186-
.get(&TypeId::of::<T>())
187-
.and_then(|rc| rc.downcast_ref())
182+
if let Some(entries) = &self.entries {
183+
entries
184+
.get(&TypeId::of::<T>())
185+
.and_then(|rc| rc.downcast_ref())
186+
} else {
187+
None
188+
}
188189
}
189190

190191
/// Returns a copy of the context with the new value included.
@@ -215,12 +216,20 @@ impl Context {
215216
/// assert_eq!(cx_with_a_and_b.get::<ValueB>(), Some(&ValueB(42)));
216217
/// ```
217218
pub fn with_value<T: 'static + Send + Sync>(&self, value: T) -> Self {
218-
let mut new_context = self.clone();
219-
new_context
220-
.entries
221-
.insert(TypeId::of::<T>(), Arc::new(value));
222-
223-
new_context
219+
let entries = if let Some(current_entries) = &self.entries {
220+
let mut inner_entries = (**current_entries).clone();
221+
inner_entries.insert(TypeId::of::<T>(), Arc::new(value));
222+
Some(Arc::new(inner_entries))
223+
} else {
224+
let mut entries = EntryMap::default();
225+
entries.insert(TypeId::of::<T>(), Arc::new(value));
226+
Some(Arc::new(entries))
227+
};
228+
Context {
229+
entries,
230+
#[cfg(feature = "trace")]
231+
span: self.span.clone(),
232+
}
224233
}
225234

226235
/// Replaces the current context on this thread with this context.
@@ -326,7 +335,7 @@ impl Context {
326335
impl fmt::Debug for Context {
327336
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328337
let mut dbg = f.debug_struct("Context");
329-
let mut entries = self.entries.len();
338+
let mut entries = self.entries.as_ref().map_or(0, |e| e.len());
330339
#[cfg(feature = "trace")]
331340
{
332341
if let Some(span) = &self.span {

0 commit comments

Comments
 (0)