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";
+
}