You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2020/09/12 12:39:07 UTC

[httpcomponents-core] 14/18: HTTPCORE-645: Chunked request streams reuse buffers between requests

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

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 9dfd5f3f869de8ae9c526ef05a8c7516db260b70
Author: Carter Kozak <c4...@gmail.com>
AuthorDate: Wed Aug 12 17:17:49 2020 -0400

    HTTPCORE-645: Chunked request streams reuse buffers between requests
    
    This adds a lazily initialized reusable buffer to the connection
    which is reused for all chunked request entities to avoid expensive
    array allocations each time a chunked request entity is sent.
---
 .../hc/core5/http/impl/io/BHttpConnectionBase.java | 13 +++++++++--
 .../hc/core5/http/impl/io/ChunkedOutputStream.java | 26 ++++++++++++++++++----
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java
index 10683a5..95168ad 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/BHttpConnectionBase.java
@@ -72,6 +72,8 @@ class BHttpConnectionBase implements BHttpConnection {
     final SessionOutputBufferImpl outbuffer;
     final BasicHttpConnectionMetrics connMetrics;
     final AtomicReference<SocketHolder> socketHolderRef;
+    // Lazily initialized chunked request buffer provided to ChunkedOutputStream.
+    private byte[] chunkedRequestBuffer;
 
     volatile ProtocolVersion version;
     volatile EndpointDetails endpointDetails;
@@ -147,13 +149,20 @@ class BHttpConnectionBase implements BHttpConnection {
         if (len >= 0) {
             return new ContentLengthOutputStream(buffer, outputStream, len);
         } else if (len == ContentLengthStrategy.CHUNKED) {
-            final int chunkSizeHint = http1Config.getChunkSizeHint() >= 0 ? http1Config.getChunkSizeHint() : 2048;
-            return new ChunkedOutputStream(buffer, outputStream, chunkSizeHint, trailers);
+            return new ChunkedOutputStream(buffer, outputStream, getChunkedRequestBuffer(), trailers);
         } else {
             return new IdentityOutputStream(buffer, outputStream);
         }
     }
 
+    private byte[] getChunkedRequestBuffer() {
+        if (chunkedRequestBuffer == null) {
+            final int chunkSizeHint = this.http1Config.getChunkSizeHint();
+            chunkedRequestBuffer = new byte[chunkSizeHint > 0 ? chunkSizeHint : 2048];
+        }
+        return chunkedRequestBuffer;
+    }
+
     protected InputStream createContentInputStream(
             final long len,
             final SessionInputBuffer buffer,
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java
index 91a0790..b8ab5fd 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/ChunkedOutputStream.java
@@ -69,25 +69,43 @@ public class ChunkedOutputStream extends OutputStream {
      *
      * @param buffer Session output buffer
      * @param outputStream Output stream
-     * @param chunkSizeHint minimal chunk size hint
+     * @param chunkCache Buffer used to aggregate smaller writes into chunks.
      * @param trailerSupplier Trailer supplier. May be {@code null}
      *
-     * @since 5.0
+     * @since 5.1
      */
     public ChunkedOutputStream(
             final SessionOutputBuffer buffer,
             final OutputStream outputStream,
-            final int chunkSizeHint,
+            final byte[] chunkCache,
             final Supplier<List<? extends Header>> trailerSupplier) {
         super();
         this.buffer = Args.notNull(buffer, "Session output buffer");
         this.outputStream = Args.notNull(outputStream, "Output stream");
-        this.cache = new byte[chunkSizeHint > 0 ? chunkSizeHint : 2048];
+        this.cache = Args.notNull(chunkCache, "Chunk cache");
         this.lineBuffer = new CharArrayBuffer(32);
         this.trailerSupplier = trailerSupplier;
     }
 
     /**
+     * Constructor taking an integer chunk size hint.
+     *
+     * @param buffer Session output buffer
+     * @param outputStream Output stream
+     * @param chunkSizeHint minimal chunk size hint
+     * @param trailerSupplier Trailer supplier. May be {@code null}
+     *
+     * @since 5.0
+     */
+    public ChunkedOutputStream(
+            final SessionOutputBuffer buffer,
+            final OutputStream outputStream,
+            final int chunkSizeHint,
+            final Supplier<List<? extends Header>> trailerSupplier) {
+        this(buffer, outputStream, new byte[chunkSizeHint > 0 ? chunkSizeHint : 2048], trailerSupplier);
+    }
+
+    /**
      * Constructor with no trailers.
      *
      * @param buffer Session output buffer