Skip to content

Commit 6468647

Browse files
perf(injection): precompute the injection tag size (#94)
# What does this PR do? This saves us reallocation of the String, as if we add only the _dd.p.dm tag and _dd.p.tid tags, we are at least at more than 32 bytes. Since the Vec smallest allocation is 8 bytes, and doubles on growth than means were perform probably 2 re-allocations in the best case scenario.
1 parent 040a625 commit 6468647

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

dd-trace-propagation/src/datadog.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -124,35 +124,38 @@ fn get_propagation_tags(
124124
tags: &HashMap<String, String>,
125125
max_length: usize,
126126
) -> Result<String, Error> {
127-
// Use a single String buffer to avoid intermediate Vec allocation
128-
let mut propagation_tags = String::new();
129-
let mut first = true;
130-
131-
for (key, value) in tags.iter() {
132-
if !key.starts_with(DATADOG_PROPAGATION_TAG_PREFIX) {
133-
continue;
134-
}
127+
// Compute size before writing to prevent reallocations
128+
let total_size: usize = tags
129+
.iter()
130+
.filter(|(k, _)| k.starts_with(DATADOG_PROPAGATION_TAG_PREFIX))
131+
.enumerate()
132+
.map(|(i, (k, v))| {
133+
// Length of the tag is len(key) + len(":") + len(value)
134+
// and then we add a "," separator prefix but only if the tag is not
135+
// the first one
136+
k.len() + v.len() + 1 + if i == 0 { 0 } else { 1 }
137+
})
138+
.sum();
139+
if total_size > max_length {
140+
return Err(Error::inject("inject_max_size", "datadog"));
141+
}
142+
let mut propagation_tags = String::with_capacity(total_size);
135143

144+
for (i, (key, value)) in tags
145+
.iter()
146+
.filter(|(k, _)| k.starts_with(DATADOG_PROPAGATION_TAG_PREFIX))
147+
.enumerate()
148+
{
136149
if !validate_tag_key(key) || !validate_tag_value(value) {
137150
return Err(Error::inject("encoding_error", "datadog"));
138151
}
139152

140-
// Estimate size to avoid multiple reallocations
141-
let entry_len = key.len() + value.len() + 1; // +1 for '='
142-
let separator_len = if first { 0 } else { 1 }; // ',' separator
143-
144-
// Check if adding this entry would exceed max_length
145-
if propagation_tags.len() + entry_len + separator_len > max_length {
146-
return Err(Error::inject("inject_max_size", "datadog"));
147-
}
148-
149-
if !first {
153+
if i != 0 {
150154
propagation_tags.push(',');
151155
}
152156
propagation_tags.push_str(key);
153157
propagation_tags.push('=');
154158
propagation_tags.push_str(value);
155-
first = false;
156159
}
157160

158161
Ok(propagation_tags)

0 commit comments

Comments
 (0)