Skip to content

Commit 6b48dab

Browse files
committed
perf: customer parser (~1.5x faster)
1 parent 00b14ac commit 6b48dab

File tree

3 files changed

+74
-97
lines changed

3 files changed

+74
-97
lines changed

include/datadog/baggage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace datadog {
1212
namespace tracing {
1313

14-
/// OpenTelemetry-like implement of the Baggage concept.
14+
/// OpenTelemetry-like implementation of the Baggage concept.
1515
/// Baggage is a key-value store meant to propagate data across services and
1616
/// processes boundaries.
1717
///

src/datadog/baggage.cpp

Lines changed: 68 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,88 @@
11
#include <datadog/baggage.h>
22

3-
#include <sstream>
3+
#include <cctype>
44

55
namespace datadog {
66
namespace tracing {
77

88
namespace {
99

10-
std::string trim(const std::string& str) {
11-
size_t start = str.find_first_not_of(' ');
12-
size_t end = str.find_last_not_of(' ');
13-
return (start == std::string::npos || end == std::string::npos)
14-
? ""
15-
: str.substr(start, end - start + 1);
16-
}
17-
1810
Expected<std::unordered_map<std::string, std::string>, Baggage::Error>
1911
parse_baggage(StringView input, size_t max_capacity) {
2012
std::unordered_map<std::string, std::string> result;
21-
std::stringstream ss(std::string{input});
22-
std::string pair;
23-
24-
// Split by commas
25-
while (std::getline(ss, pair, ',')) {
26-
size_t equalPos = pair.find('=');
13+
if (input.empty()) return result;
14+
15+
enum class state : char {
16+
leading_spaces_key,
17+
key,
18+
leading_spaces_value,
19+
value
20+
} internal_state = state::leading_spaces_key;
21+
22+
size_t beg = 0;
23+
size_t tmp_end = 0;
24+
25+
StringView key;
26+
StringView value;
27+
28+
const size_t end = input.size();
29+
30+
for (size_t i = 0; i < end; ++i) {
31+
switch (internal_state) {
32+
case state::leading_spaces_key: {
33+
if (!std::isspace(input[i])) {
34+
if (result.size() == max_capacity)
35+
return Baggage::Error::MAXIMUM_CAPACITY_REACHED;
36+
37+
beg = i;
38+
tmp_end = i;
39+
internal_state = state::key;
40+
}
41+
} break;
42+
43+
case state::key: {
44+
if (input[i] == ',') {
45+
return Baggage::Error::MALFORMED_BAGGAGE_HEADER;
46+
} else if (input[i] == '=') {
47+
key = StringView{input.data() + beg, tmp_end - beg + 1};
48+
internal_state = state::leading_spaces_value;
49+
} else if (!std::isspace(input[i])) {
50+
tmp_end = i;
51+
}
52+
} break;
53+
54+
case state::leading_spaces_value: {
55+
if (!std::isspace(input[i])) {
56+
beg = i;
57+
tmp_end = i;
58+
internal_state = state::value;
59+
}
60+
} break;
61+
62+
case state::value: {
63+
if (input[i] == ',') {
64+
value = StringView{input.data() + beg, tmp_end - beg + 1};
65+
result.emplace(std::string(key), std::string(value));
66+
beg = i;
67+
tmp_end = i;
68+
internal_state = state::leading_spaces_key;
69+
} else if (!std::isspace(input[i])) {
70+
tmp_end = i;
71+
}
72+
} break;
73+
}
74+
}
2775

28-
if (equalPos == std::string::npos)
29-
return Baggage::Error::MALFORMED_BAGGAGE_HEADER;
76+
if (internal_state != state::value) {
77+
return Baggage::Error::MALFORMED_BAGGAGE_HEADER;
78+
}
3079

31-
// Extract key and value, then trim spaces
32-
std::string key = trim(pair.substr(0, equalPos));
33-
if (key.empty()) return Baggage::Error::MALFORMED_BAGGAGE_HEADER;
34-
if (result.size() == max_capacity)
35-
return Baggage::Error::MAXIMUM_CAPACITY_REACHED;
80+
value = StringView{input.data() + beg, tmp_end - beg + 1};
81+
result.emplace(std::string(key), std::string(value));
3682

37-
std::string value = trim(pair.substr(equalPos + 1));
38-
result[key] = value;
39-
}
4083
return result;
4184
}
4285

43-
/*constexpr bool is_space(char c) {*/
44-
/* return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c ==
45-
* '\v';*/
46-
/*}*/
47-
48-
/*Expected<std::unordered_map<std::string, std::string>, Baggage::Error>*/
49-
/*parse_baggage(StringView input, size_t max_capacity) {*/
50-
/* enum class state : char {*/
51-
/* swallow,*/
52-
/* key,*/
53-
/* value*/
54-
/* } internal_state = state::swallow;*/
55-
/**/
56-
/* std::unordered_map<std::string, std::string> result;*/
57-
/**/
58-
/* size_t beg = 0;*/
59-
/* size_t tmp_end = 0;*/
60-
/**/
61-
/* StringView key;*/
62-
/* StringView value;*/
63-
/**/
64-
/* const size_t end = input.size();*/
65-
/**/
66-
/* for (size_t i = 0; i < end; ++i) {*/
67-
/* switch(internal_state) {*/
68-
/* case state::swallow: {*/
69-
/* if (!is_space(input[i])) {*/
70-
/* beg = i;*/
71-
/* internal_state = state::key;*/
72-
/* }*/
73-
/* } break;*/
74-
/**/
75-
/* case state::key: {*/
76-
/* if (input[i] == '=') {*/
77-
/* if (result.size() == max_capacity) return
78-
* Baggage::Error::MAXIMUM_CAPACITY_REACHED;*/
79-
/**/
80-
/* key = StringView{input.data() + beg, tmp_end - beg};*/
81-
/* beg = i;*/
82-
/* tmp_end = i;*/
83-
/* internal_state = state::value;*/
84-
/* } else if (!is_space(input[i])) {*/
85-
/* tmp_end = i;*/
86-
/* }*/
87-
/* } break;*/
88-
/**/
89-
/* case state::value: {*/
90-
/* if (input[i] == ',') {*/
91-
/* value = StringView{input.data() + beg, tmp_end - beg};*/
92-
/* result.emplace(std::string(key), std::string(value));*/
93-
/* beg = i;*/
94-
/* tmp_end = i;*/
95-
/* internal_state = state::swallow;*/
96-
/* } else if (!is_space(input[i])) {*/
97-
/* tmp_end = i;*/
98-
/* }*/
99-
/* } break;*/
100-
/**/
101-
/* }*/
102-
/* }*/
103-
/**/
104-
/* if (internal_state != state::value) {*/
105-
/* return Baggage::Error::MALFORMED_BAGGAGE_HEADER;*/
106-
/* }*/
107-
/**/
108-
/* value = StringView{input.data() + beg, tmp_end - beg};*/
109-
/* result.emplace(std::string(key), std::string(value));*/
110-
/**/
111-
/* return result;*/
112-
/*}*/
113-
11486
} // namespace
11587

11688
Baggage::Baggage(size_t max_capacity) : max_capacity_(max_capacity) {}

test/test_baggage.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ BAGGAGE_TEST("extract") {
3838
"",
3939
Baggage(),
4040
},
41+
{
42+
"only spaces",
43+
" ",
44+
Baggage::Error::MALFORMED_BAGGAGE_HEADER,
45+
},
4146
{
4247
"valid",
4348
"key1=value1,key2=value2",

0 commit comments

Comments
 (0)