From 1b8ad3e1604d1b31f690668a4ed352d58b2621ef Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 20 Mar 2023 14:42:20 -0700 Subject: [PATCH] ircd::resource: Optimize response w/ iov for fused head and content. --- include/ircd/resource/response.h | 2 +- ircd/resource.cc | 36 +++++++++++++++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/include/ircd/resource/response.h b/include/ircd/resource/response.h index ead3810e6..5de5be08e 100644 --- a/include/ircd/resource/response.h +++ b/include/ircd/resource/response.h @@ -39,7 +39,7 @@ struct ircd::resource::response static const size_t HEAD_BUF_SZ; static conf::item access_control_allow_origin; - response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {}); + response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {}, const string_view &content = {}); response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view &); response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {}); response(client &, const json::object &str, const http::code & = http::OK); diff --git a/ircd/resource.cc b/ircd/resource.cc index c105f0cc6..7b573fd26 100644 --- a/ircd/resource.cc +++ b/ircd/resource.cc @@ -1367,17 +1367,8 @@ ircd::resource::response::response(client &client, content_type, size(content), headers, + content, }; - - // All content gets sent - const size_t written - { - size(content)? - client.write_all(content): - 0 - }; - - assert(written == size(content)); } decltype(ircd::resource::response::access_control_allow_origin) @@ -1392,8 +1383,12 @@ ircd::resource::response::response(client &client, const http::code &code, const string_view &content_type, const size_t &content_length, - const string_view &headers) + const string_view &headers, + const string_view &content) { + // content may be empty if the caller wants to send it themselves, but + // either way the type and length must still be passed by caller. + assert(!content || content_length); assert(!content_length || !empty(content_type)); const auto request_time @@ -1430,13 +1425,20 @@ ircd::resource::response::response(client &client, if(unlikely(!head.remaining())) throw panic { - "HTTP headers too large for buffer of %zu", sizeof(head_buf) + "HTTP headers too large for buffer of %zu", + sizeof(head_buf), }; - size_t wrote_head {0}; + const const_buffer iov[] + { + head.completed(), + content, + }; + + size_t wrote {0}; std::exception_ptr eptr; try { - wrote_head += client.write_all(head.completed()); + wrote += client.write_all(iov); } catch(...) { @@ -1453,17 +1455,17 @@ ircd::resource::response::response(client &client, log::logf { log, level, - "%s HTTP %u `%s' %s in %s; %s content-length:%s head-length:%zu %s%s", + "%s HTTP %u `%s' %s in %s; %s head:%zu content:%s %s%s", loghead(client), uint(code), client.request.head.path, http::status(code), rtime, content_type, + size(iov[0]), ssize_t(content_length) >= 0? lex_cast(content_length): "chunked"_sv, - wrote_head, eptr? "error:"_sv: string_view{}, @@ -1474,7 +1476,7 @@ ircd::resource::response::response(client &client, if(unlikely(eptr)) std::rethrow_exception(eptr); - assert(wrote_head == size(head.completed())); + assert(wrote == buffers::size(vector_view(iov))); } ///////////////////////////////////////////////////////////////////////////////