Skip to content

Reduce string copying. #135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions include/aws/http/response.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* permissions and limitations under the License.
*/

#include "aws/lambda-runtime/outcome.h"

#include <string>
#include <vector>
#include <algorithm>
Expand All @@ -31,7 +33,7 @@ class response {
inline void add_header(std::string name, std::string const& value);
inline void append_body(const char* p, size_t sz);
inline bool has_header(char const* header) const;
inline std::string const& get_header(char const* header) const;
inline lambda_runtime::outcome<std::string, bool> get_header(char const* header) const;
inline response_code get_response_code() const { return m_response_code; }
inline void set_response_code(aws::http::response_code c);
inline void set_content_type(char const* ct);
Expand Down Expand Up @@ -140,7 +142,7 @@ inline std::string const& response::get_body() const
inline void response::add_header(std::string name, std::string const& value)
{
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
m_headers.emplace_back(name, value);
m_headers.emplace_back(std::move(name), value);
}

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

inline std::string const& response::get_header(char const* header) const
inline lambda_runtime::outcome<std::string, bool> response::get_header(char const* header) const
{
auto it = std::find_if(m_headers.begin(), m_headers.end(), [header](std::pair<std::string, std::string> const& p) {
return p.first == header;
});
assert(it != m_headers.end());

if (it == m_headers.end()) {
return false;
}
return it->second;
}

Expand Down
24 changes: 20 additions & 4 deletions include/aws/lambda-runtime/outcome.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,20 @@ class outcome {
}
}

~outcome()
~outcome() { destroy(); }

outcome& operator=(outcome&& other) noexcept
{
if (m_success) {
m_s.~TResult();
assert(this != &other);
destroy();
if (other.m_success) {
new (&m_s) TResult(std::move(other.m_s));
}
else {
m_f.~TFailure();
new (&m_f) TFailure(std::move(other.m_f));
}
m_success = other.m_success;
return *this;
}

TResult const& get_result() const&
Expand Down Expand Up @@ -86,6 +92,16 @@ class outcome {
bool is_success() const { return m_success; }

private:
void destroy()
{
if (m_success) {
m_s.~TResult();
}
else {
m_f.~TFailure();
}
}

union {
TResult m_s;
TFailure m_f;
Expand Down
36 changes: 20 additions & 16 deletions src/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@ static size_t write_header(char* ptr, size_t size, size_t nmemb, void* userdata)
if (ptr[i] != ':') {
continue;
}
std::string key{ptr, i};
std::string value{ptr + i + 1, nmemb - i - 1};
resp->add_header(trim(key), trim(value));
resp->add_header(trim({ptr, i}), trim({ptr + i + 1, nmemb - i - 1}));
break;
}
return size * nmemb;
Expand Down Expand Up @@ -266,32 +264,38 @@ runtime::next_outcome runtime::get_next()
return resp.get_response_code();
}

if (!resp.has_header(REQUEST_ID_HEADER)) {
auto out = resp.get_header(REQUEST_ID_HEADER);
if (!out.is_success()) {
logging::log_error(LOG_TAG, "Failed to find header %s in response", REQUEST_ID_HEADER);
return aws::http::response_code::REQUEST_NOT_MADE;
}
invocation_request req;
req.payload = resp.get_body();
req.request_id = resp.get_header(REQUEST_ID_HEADER);
req.request_id = std::move(out).get_result();

if (resp.has_header(TRACE_ID_HEADER)) {
req.xray_trace_id = resp.get_header(TRACE_ID_HEADER);
out = resp.get_header(TRACE_ID_HEADER);
if (out.is_success()) {
req.xray_trace_id = std::move(out).get_result();
}

if (resp.has_header(CLIENT_CONTEXT_HEADER)) {
req.client_context = resp.get_header(CLIENT_CONTEXT_HEADER);
out = resp.get_header(CLIENT_CONTEXT_HEADER);
if (out.is_success()) {
req.client_context = std::move(out).get_result();
}

if (resp.has_header(COGNITO_IDENTITY_HEADER)) {
req.cognito_identity = resp.get_header(COGNITO_IDENTITY_HEADER);
out = resp.get_header(COGNITO_IDENTITY_HEADER);
if (out.is_success()) {
req.cognito_identity = std::move(out).get_result();
}

if (resp.has_header(FUNCTION_ARN_HEADER)) {
req.function_arn = resp.get_header(FUNCTION_ARN_HEADER);
out = resp.get_header(FUNCTION_ARN_HEADER);
if (out.is_success()) {
req.function_arn = std::move(out).get_result();
}

if (resp.has_header(DEADLINE_MS_HEADER)) {
auto const& deadline_string = resp.get_header(DEADLINE_MS_HEADER);
out = resp.get_header(DEADLINE_MS_HEADER);
if (out.is_success()) {
auto const& deadline_string = std::move(out).get_result();
constexpr int base = 10;
unsigned long ms = strtoul(deadline_string.c_str(), nullptr, base);
assert(ms > 0);
Expand All @@ -303,7 +307,7 @@ runtime::next_outcome runtime::get_next()
req.payload.c_str(),
static_cast<int64_t>(req.get_time_remaining().count()));
}
return next_outcome(req);
return {req};
}

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