You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by mg...@apache.org on 2025/04/22 07:58:16 UTC

(kudu) branch branch-1.18.x updated: [webserver] reduce memory allocations and copying for responses

This is an automated email from the ASF dual-hosted git repository.

mgreber pushed a commit to branch branch-1.18.x
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/branch-1.18.x by this push:
     new 1a1fbc1a9 [webserver] reduce memory allocations and copying for responses
1a1fbc1a9 is described below

commit 1a1fbc1a913eacab521558c2d2200f7b1bb2a67d
Author: Alexey Serbin <al...@apache.org>
AuthorDate: Thu Mar 6 20:42:41 2025 -0800

    [webserver] reduce memory allocations and copying for responses
    
    This patch optimizes handling the WebResponse::response field, swapping
    the underlying rdbuf in ostringstream instead of materializing it
    as std::string and copying over the data from one stream to another.
    
    There are no functional modifications in this changelist.
    
    Change-Id: I4085ab8150ecd04972d9eac8633226845b365830
    Reviewed-on: http://gerrit.cloudera.org:8080/22796
    Reviewed-by: Yifan Zhang <ch...@163.com>
    Reviewed-by: Abhishek Chennaka <ac...@cloudera.com>
    Tested-by: Alexey Serbin <al...@apache.org>
    (cherry picked from commit 887a87dd9c6cfc29999e0eb9c55e559cdeefe59f)
    Reviewed-on: http://gerrit.cloudera.org:8080/22798
---
 src/kudu/server/webserver.cc | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/kudu/server/webserver.cc b/src/kudu/server/webserver.cc
index c8c79ff6a..61012abd1 100644
--- a/src/kudu/server/webserver.cc
+++ b/src/kudu/server/webserver.cc
@@ -40,6 +40,7 @@
 #include <unordered_set>
 #include <utility>
 #include <vector>
+// IWYU pragma: no_include <__string>
 
 #include <boost/algorithm/string/case_conv.hpp>
 #include <gflags/gflags.h>
@@ -697,27 +698,28 @@ void Webserver::SendResponse(struct sq_connection* connection,
     DCHECK(req);
     stringstream ss;
     RenderMainTemplate(*req, resp->output.str(), &ss);
-    resp->output.str(ss.str());
+    resp->output.rdbuf()->swap(*ss.rdbuf());
   }
 
   // Check if gzip compression is accepted by the caller. If so, compress the
   // content and replace the prerendered output.
-  const char* accept_encoding_str = sq_get_header(connection, "Accept-Encoding");
+  auto& output = resp->output;
   bool is_compressed = false;
+  const char* accept_encoding_str = sq_get_header(connection, "Accept-Encoding");
   vector<string> encodings = strings::Split(accept_encoding_str, ",");
   for (string& encoding : encodings) {
     StripWhiteSpace(&encoding);
     if (encoding == "gzip") {
       // Don't bother compressing empty content.
-      string uncompressed = resp->output.str();
-      if (uncompressed.empty()) {
+      DCHECK(output.good());
+      if (output.tellp() == 0) {
         break;
       }
 
       ostringstream oss;
-      const auto s = zlib::Compress(uncompressed, &oss);
+      const auto s = zlib::Compress(output.str(), &oss);
       if (PREDICT_TRUE(s.ok())) {
-        resp->output.str(oss.str());
+        output.swap(oss);
         is_compressed = true;
       } else {
         LOG(WARNING) << "Could not compress output: " << s.ToString();
@@ -728,7 +730,7 @@ void Webserver::SendResponse(struct sq_connection* connection,
 
   // We've deferred constructing the content for as long as possible; we must
   // do so now so that we can determine the content length.
-  string body = resp->output.str();
+  string body = output.str();
 
   // Buffers up the headers and content as follows:
   //
@@ -850,7 +852,7 @@ void Webserver::RegisterPathHandler(const string& path, const string& alias,
     if (render_path != "/home" || is_started_) {
       stringstream out;
       Render(render_path, resp.output, style_mode, &out);
-      rendered_resp->output << out.rdbuf();
+      rendered_resp->output.rdbuf()->swap(*out.rdbuf());
     }
   };
   RegisterPrerenderedPathHandler(path, alias, wrapped_cb, style_mode, is_on_nav_bar);