From e30b5b55806b31d1a61e2885b854dd7b8da1a07a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 3 May 2011 10:55:35 -0700 Subject: Make Apache HttpClient play nice with large kernel socket buffers. Given the large maximum size likely to be set for kernel socket buffers on LTE devices, we need to stop Apache HttpClient from allocating some integer multiple of that size on the heap for each socket. On one device, 16 HTTP connections would fill the heap. Bug: 3514259 Change-Id: I888c03b6ad4b7ca444c2c423b097a3f76390846b --- src/org/apache/http/impl/io/SocketInputBuffer.java | 51 ++++++---------------- .../apache/http/impl/io/SocketOutputBuffer.java | 31 +++++-------- 2 files changed, 24 insertions(+), 58 deletions(-) diff --git a/src/org/apache/http/impl/io/SocketInputBuffer.java b/src/org/apache/http/impl/io/SocketInputBuffer.java index 9e09436..7d4323b 100644 --- a/src/org/apache/http/impl/io/SocketInputBuffer.java +++ b/src/org/apache/http/impl/io/SocketInputBuffer.java @@ -34,6 +34,7 @@ package org.apache.http.impl.io; import java.io.IOException; import java.io.InterruptedIOException; import java.net.Socket; +import java.net.SocketTimeoutException; import java.net.SocketTimeoutException; import org.apache.http.params.HttpParams; @@ -45,55 +46,31 @@ import org.apache.http.params.HttpParams; * @author Oleg Kalnichevski * * @version $Revision: 560358 $ - * + * * @since 4.0 */ public class SocketInputBuffer extends AbstractSessionInputBuffer { - static private final Class SOCKET_TIMEOUT_CLASS = SocketTimeoutExceptionClass(); - - /** - * Returns SocketTimeoutExceptionClass or null if the class - * does not exist. - * - * @return SocketTimeoutExceptionClass, or null if unavailable. - */ - static private Class SocketTimeoutExceptionClass() { - try { - return Class.forName("java.net.SocketTimeoutException"); - } catch (ClassNotFoundException e) { - return null; - } - } - - private static boolean isSocketTimeoutException(final InterruptedIOException e) { - if (SOCKET_TIMEOUT_CLASS != null) { - return SOCKET_TIMEOUT_CLASS.isInstance(e); - } else { - return true; - } - } - private final Socket socket; - + public SocketInputBuffer( - final Socket socket, - int buffersize, + final Socket socket, + int buffersize, final HttpParams params) throws IOException { super(); if (socket == null) { throw new IllegalArgumentException("Socket may not be null"); } this.socket = socket; - if (buffersize < 0) { - buffersize = socket.getReceiveBufferSize(); - } - if (buffersize < 1024) { - buffersize = 1024; - } - init(socket.getInputStream(), buffersize, params); + // BEGIN android-changed + // Workaround for http://b/3514259. We take 'buffersize' as a hint in + // the weakest sense, and always use an 8KiB heap buffer and leave the + // kernel buffer size alone, trusting the system to have set a + // network-appropriate default. + init(socket.getInputStream(), 8192, params); + // END android-changed } - + public boolean isDataAvailable(int timeout) throws IOException { boolean result = hasBufferedData(); if (!result) { @@ -103,7 +80,7 @@ public class SocketInputBuffer extends AbstractSessionInputBuffer { fillBuffer(); result = hasBufferedData(); } catch (InterruptedIOException e) { - if (!isSocketTimeoutException(e)) { + if (!(e instanceof SocketTimeoutException)) { throw e; } } finally { diff --git a/src/org/apache/http/impl/io/SocketOutputBuffer.java b/src/org/apache/http/impl/io/SocketOutputBuffer.java index efb91e9..c1d3b49 100644 --- a/src/org/apache/http/impl/io/SocketOutputBuffer.java +++ b/src/org/apache/http/impl/io/SocketOutputBuffer.java @@ -43,37 +43,26 @@ import org.apache.http.params.HttpParams; * @author Oleg Kalnichevski * * @version $Revision: 560358 $ - * + * * @since 4.0 */ public class SocketOutputBuffer extends AbstractSessionOutputBuffer { public SocketOutputBuffer( - final Socket socket, + final Socket socket, int buffersize, final HttpParams params) throws IOException { super(); if (socket == null) { throw new IllegalArgumentException("Socket may not be null"); } - if (buffersize < 0) { - buffersize = socket.getReceiveBufferSize(); -// BEGIN android-changed - // Workaround for http://b/issue?id=1083103. - if (buffersize > 8096) { - buffersize = 8096; - } -// END android-changed - } - if (buffersize < 1024) { - buffersize = 1024; - } - -// BEGIN android-changed - socket.setSendBufferSize(buffersize * 3); -// END andrdoid-changed - - init(socket.getOutputStream(), buffersize, params); + // BEGIN android-changed + // Workaround for http://b/1083103 and http://b/3514259. We take + // 'buffersize' as a hint in the weakest sense, and always use + // an 8KiB heap buffer and leave the kernel buffer size alone, + // trusting the system to have set a network-appropriate default. + init(socket.getOutputStream(), 8192, params); + // END android-changed } - + } -- cgit v1.1