Skip to content

Commit 4aa6639

Browse files
marcomagdyMarco Magdy
and
Marco Magdy
authored
Reduce string copying. (#135)
* Reduce string copying. Optimized a few unnecessary string copies that should have been moves to begin with. Additionally, I noticed that we're scanning the headers twice once to test if a given header exists and another to get its value, that is a perfect use case for std::optional, but since we need to stay compatible with C++11 and C++14, we can use the 'outcome' class instead. * Fixup: Move state boolean in move assignment Co-authored-by: Marco Magdy <[email protected]>
1 parent 1f2ed6e commit 4aa6639

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

include/aws/http/response.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* permissions and limitations under the License.
1515
*/
1616

17+
#include "aws/lambda-runtime/outcome.h"
18+
1719
#include <string>
1820
#include <vector>
1921
#include <algorithm>
@@ -31,7 +33,7 @@ class response {
3133
inline void add_header(std::string name, std::string const& value);
3234
inline void append_body(const char* p, size_t sz);
3335
inline bool has_header(char const* header) const;
34-
inline std::string const& get_header(char const* header) const;
36+
inline lambda_runtime::outcome<std::string, bool> get_header(char const* header) const;
3537
inline response_code get_response_code() const { return m_response_code; }
3638
inline void set_response_code(aws::http::response_code c);
3739
inline void set_content_type(char const* ct);
@@ -140,7 +142,7 @@ inline std::string const& response::get_body() const
140142
inline void response::add_header(std::string name, std::string const& value)
141143
{
142144
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
143-
m_headers.emplace_back(name, value);
145+
m_headers.emplace_back(std::move(name), value);
144146
}
145147

146148
inline void response::append_body(const char* p, size_t sz)
@@ -161,12 +163,15 @@ inline bool response::has_header(char const* header) const
161163
});
162164
}
163165

164-
inline std::string const& response::get_header(char const* header) const
166+
inline lambda_runtime::outcome<std::string, bool> response::get_header(char const* header) const
165167
{
166168
auto it = std::find_if(m_headers.begin(), m_headers.end(), [header](std::pair<std::string, std::string> const& p) {
167169
return p.first == header;
168170
});
169-
assert(it != m_headers.end());
171+
172+
if (it == m_headers.end()) {
173+
return false;
174+
}
170175
return it->second;
171176
}
172177

include/aws/lambda-runtime/outcome.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,20 @@ class outcome {
4949
}
5050
}
5151

52-
~outcome()
52+
~outcome() { destroy(); }
53+
54+
outcome& operator=(outcome&& other) noexcept
5355
{
54-
if (m_success) {
55-
m_s.~TResult();
56+
assert(this != &other);
57+
destroy();
58+
if (other.m_success) {
59+
new (&m_s) TResult(std::move(other.m_s));
5660
}
5761
else {
58-
m_f.~TFailure();
62+
new (&m_f) TFailure(std::move(other.m_f));
5963
}
64+
m_success = other.m_success;
65+
return *this;
6066
}
6167

6268
TResult const& get_result() const&
@@ -86,6 +92,16 @@ class outcome {
8692
bool is_success() const { return m_success; }
8793

8894
private:
95+
void destroy()
96+
{
97+
if (m_success) {
98+
m_s.~TResult();
99+
}
100+
else {
101+
m_f.~TFailure();
102+
}
103+
}
104+
89105
union {
90106
TResult m_s;
91107
TFailure m_f;

src/runtime.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,7 @@ static size_t write_header(char* ptr, size_t size, size_t nmemb, void* userdata)
116116
if (ptr[i] != ':') {
117117
continue;
118118
}
119-
std::string key{ptr, i};
120-
std::string value{ptr + i + 1, nmemb - i - 1};
121-
resp->add_header(trim(key), trim(value));
119+
resp->add_header(trim({ptr, i}), trim({ptr + i + 1, nmemb - i - 1}));
122120
break;
123121
}
124122
return size * nmemb;
@@ -266,32 +264,38 @@ runtime::next_outcome runtime::get_next()
266264
return resp.get_response_code();
267265
}
268266

269-
if (!resp.has_header(REQUEST_ID_HEADER)) {
267+
auto out = resp.get_header(REQUEST_ID_HEADER);
268+
if (!out.is_success()) {
270269
logging::log_error(LOG_TAG, "Failed to find header %s in response", REQUEST_ID_HEADER);
271270
return aws::http::response_code::REQUEST_NOT_MADE;
272271
}
273272
invocation_request req;
274273
req.payload = resp.get_body();
275-
req.request_id = resp.get_header(REQUEST_ID_HEADER);
274+
req.request_id = std::move(out).get_result();
276275

277-
if (resp.has_header(TRACE_ID_HEADER)) {
278-
req.xray_trace_id = resp.get_header(TRACE_ID_HEADER);
276+
out = resp.get_header(TRACE_ID_HEADER);
277+
if (out.is_success()) {
278+
req.xray_trace_id = std::move(out).get_result();
279279
}
280280

281-
if (resp.has_header(CLIENT_CONTEXT_HEADER)) {
282-
req.client_context = resp.get_header(CLIENT_CONTEXT_HEADER);
281+
out = resp.get_header(CLIENT_CONTEXT_HEADER);
282+
if (out.is_success()) {
283+
req.client_context = std::move(out).get_result();
283284
}
284285

285-
if (resp.has_header(COGNITO_IDENTITY_HEADER)) {
286-
req.cognito_identity = resp.get_header(COGNITO_IDENTITY_HEADER);
286+
out = resp.get_header(COGNITO_IDENTITY_HEADER);
287+
if (out.is_success()) {
288+
req.cognito_identity = std::move(out).get_result();
287289
}
288290

289-
if (resp.has_header(FUNCTION_ARN_HEADER)) {
290-
req.function_arn = resp.get_header(FUNCTION_ARN_HEADER);
291+
out = resp.get_header(FUNCTION_ARN_HEADER);
292+
if (out.is_success()) {
293+
req.function_arn = std::move(out).get_result();
291294
}
292295

293-
if (resp.has_header(DEADLINE_MS_HEADER)) {
294-
auto const& deadline_string = resp.get_header(DEADLINE_MS_HEADER);
296+
out = resp.get_header(DEADLINE_MS_HEADER);
297+
if (out.is_success()) {
298+
auto const& deadline_string = std::move(out).get_result();
295299
constexpr int base = 10;
296300
unsigned long ms = strtoul(deadline_string.c_str(), nullptr, base);
297301
assert(ms > 0);
@@ -303,7 +307,7 @@ runtime::next_outcome runtime::get_next()
303307
req.payload.c_str(),
304308
static_cast<int64_t>(req.get_time_remaining().count()));
305309
}
306-
return next_outcome(req);
310+
return {req};
307311
}
308312

309313
runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response)

0 commit comments

Comments
 (0)