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 2010/03/15 21:22:14 UTC

svn commit: r923419 - in /httpcomponents/httpcore/trunk: ./ httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/ httpcore/src/main/java/org/apache/http/impl/io/ httpcore/src/main/java/org/apache/http/params/

Author: olegk
Date: Mon Mar 15 20:22:13 2010
New Revision: 923419

URL: http://svn.apache.org/viewvc?rev=923419&view=rev
Log:
HTTPCORE-177: Reduce intermediate data buffering by reading large chunks of data directly from the underlying socket stream

Modified:
    httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
    httpcomponents/httpcore/trunk/httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/HttpCoreServer.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
    httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreConnectionPNames.java

Modified: httpcomponents/httpcore/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/RELEASE_NOTES.txt?rev=923419&r1=923418&r2=923419&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpcore/trunk/RELEASE_NOTES.txt Mon Mar 15 20:22:13 2010
@@ -1,5 +1,9 @@
 Changes since 4.1-ALPHA1
 
+* [HTTPCORE-177] Reduce intermediate data buffering by reading large chunks of data directly from 
+  the underlying socket stream. This results in improved performance of blocking read operations.
+  Contributed by Oleg Kalnichevski <olegk at apache.org> 
+
 * [HTTPCORE-220] IdentityDecoder fails to detect end of stream when using file channels.
   Contributed by Asankha C. Perera <asankha at apache.org> 
 

Modified: httpcomponents/httpcore/trunk/httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/HttpCoreServer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/HttpCoreServer.java?rev=923419&r1=923418&r2=923419&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/HttpCoreServer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-benchmark/src/main/java/org/apache/http/benchmark/httpcore/HttpCoreServer.java Mon Mar 15 20:22:13 2010
@@ -65,6 +65,7 @@ public class HttpCoreServer implements H
         params
             .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 10000)
             .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 12 * 1024)
+            .setIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 1024)
             .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
             .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpCore-Test/1.1");
 
@@ -81,9 +82,9 @@ public class HttpCoreServer implements H
         HttpService httpservice = new HttpService(
                 httpproc, 
                 new DefaultConnectionReuseStrategy(), 
-                new DefaultHttpResponseFactory());
-        httpservice.setParams(params);
-        httpservice.setHandlerResolver(reqistry);
+                new DefaultHttpResponseFactory(),
+                reqistry, 
+                params);
         
         this.workers = new ConcurrentLinkedQueue<HttpWorker>();
         this.listener = new HttpListener(

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java?rev=923419&r1=923418&r2=923419&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionInputBuffer.java Mon Mar 15 20:22:13 2010
@@ -54,6 +54,7 @@ import org.apache.http.util.CharArrayBuf
  * <ul>
  *  <li>{@link org.apache.http.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
  *  <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
+ *  <li>{@link org.apache.http.params.CoreConnectionPNames#MIN_CHUNK_LIMIT}</li>
  * </ul>
  * @since 4.0
  */
@@ -69,6 +70,7 @@ public abstract class AbstractSessionInp
     private String charset = HTTP.US_ASCII;
     private boolean ascii = true;
     private int maxLineLen = -1;
+    private int minChunkLimit = 512;
     
     private HttpTransportMetricsImpl metrics;
     
@@ -98,6 +100,7 @@ public abstract class AbstractSessionInp
         this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
                      || this.charset.equalsIgnoreCase(HTTP.ASCII);
         this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1);
+        this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
         this.metrics = new HttpTransportMetricsImpl();
     }
     
@@ -143,20 +146,29 @@ public abstract class AbstractSessionInp
         if (b == null) {
             return 0;
         }
-        int noRead = 0;
-        while (!hasBufferedData()) {
-            noRead = fillBuffer();
-            if (noRead == -1) {
-                return -1;
+        if (hasBufferedData()) {
+            int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+            System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+            this.bufferpos += chunk;
+            return chunk;
+        }
+        // If the remaining capacity is big enough, read directly from the 
+        // underlying input stream bypassing the buffer.
+        if (len > this.minChunkLimit) {
+            return this.instream.read(b, off, len);
+        } else {
+            // otherwise read to the buffer first
+            while (!hasBufferedData()) {
+                int noRead = fillBuffer();
+                if (noRead == -1) {
+                    return -1;
+                }
             }
+            int chunk = Math.min(len, this.bufferlen - this.bufferpos);
+            System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
+            this.bufferpos += chunk;
+            return chunk;
         }
-        int chunk = this.bufferlen - this.bufferpos;
-        if (chunk > len) {
-            chunk = len;
-        }
-        System.arraycopy(this.buffer, this.bufferpos, b, off, chunk);
-        this.bufferpos += chunk;
-        return chunk;
     }
     
     public int read(final byte[] b) throws IOException {

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java?rev=923419&r1=923418&r2=923419&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java Mon Mar 15 20:22:13 2010
@@ -32,6 +32,7 @@ import java.io.OutputStream;
 
 import org.apache.http.io.SessionOutputBuffer;
 import org.apache.http.io.HttpTransportMetrics;
+import org.apache.http.params.CoreConnectionPNames;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.protocol.HTTP;
@@ -50,6 +51,7 @@ import org.apache.http.util.CharArrayBuf
  * class: 
  * <ul>
  *  <li>{@link org.apache.http.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
+ *  <li>{@link org.apache.http.params.CoreConnectionPNames#MIN_CHUNK_LIMIT}</li>
  * </ul>
  * <p>
  *
@@ -59,13 +61,12 @@ public abstract class AbstractSessionOut
 
     private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
     
-    private static final int MAX_CHUNK = 256;
-    
     private OutputStream outstream;
     private ByteArrayBuffer buffer;
         
     private String charset = HTTP.US_ASCII;
     private boolean ascii = true;
+    private int minChunkLimit = 512;
     
     private HttpTransportMetricsImpl metrics;
     
@@ -91,6 +92,7 @@ public abstract class AbstractSessionOut
         this.charset = HttpProtocolParams.getHttpElementCharset(params); 
         this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
                      || this.charset.equalsIgnoreCase(HTTP.ASCII);
+        this.minChunkLimit = params.getIntParameter(CoreConnectionPNames.MIN_CHUNK_LIMIT, 512);
         this.metrics = new HttpTransportMetricsImpl();
     }
     
@@ -112,10 +114,10 @@ public abstract class AbstractSessionOut
         if (b == null) {
             return;
         }
-        // Do not want to buffer largish chunks
-        // if the byte array is larger then MAX_CHUNK
+        // Do not want to buffer large-ish chunks
+        // if the byte array is larger then MIN_CHUNK_LIMIT
         // write it directly to the output stream
-        if (len > MAX_CHUNK || len > this.buffer.capacity()) {
+        if (len > this.minChunkLimit || len > this.buffer.capacity()) {
             // flush the buffer
             flushBuffer();
             // write directly to the out stream

Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreConnectionPNames.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreConnectionPNames.java?rev=923419&r1=923418&r2=923419&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreConnectionPNames.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/params/CoreConnectionPNames.java Mon Mar 15 20:22:13 2010
@@ -137,4 +137,17 @@ public interface CoreConnectionPNames {
      */
     public static final String MAX_HEADER_COUNT = "http.connection.max-header-count";
 
+    /**
+     * Defines the size limit below which data chunks should be buffered in a session I/O buffer 
+     * in order to minimize native method invocations on the underlying network socket. 
+     * The optimal value of this parameter can be platform specific and defines a trade-off 
+     * between performance of memory copy operations and that of native method invocation.
+     * <p>
+     * This parameter expects a value of type {@link Integer}.
+     * </p>
+     * 
+     * @since 4.1
+     */
+    public static final String MIN_CHUNK_LIMIT = "http.connection.min-chunk-limit";
+
 }