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 2005/10/23 20:21:11 UTC

svn commit: r327828 - in /jakarta/httpclient/trunk/http-core/src: java/org/apache/http/impl/io/ java/org/apache/http/io/ java/org/apache/http/params/ java/org/apache/http/util/ test/org/apache/http/impl/ test/org/apache/http/util/

Author: olegk
Date: Sun Oct 23 11:20:46 2005
New Revision: 327828

URL: http://svn.apache.org/viewcvs?rev=327828&view=rev
Log:
Another round of performance optimization

* Abstract HTTP data receiver extended with a method to read HTTP line into a char buffer. This method is intended to reduce the amount of garbage generated when parsing HTTP lines
* Abstract HTTP data receiver uses byte to char cast when converting raw bytes to US-ASCII chars

Modified:
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/impl/io/AbstractHttpDataReceiver.java
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/io/HttpDataReceiver.java
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/params/HttpProtocolParams.java
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/CharArrayBuffer.java
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EncodingUtils.java
    jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EntityUtils.java
    jakarta/httpclient/trunk/http-core/src/test/org/apache/http/impl/TestHttpDataReceiverAndTransmitter.java
    jakarta/httpclient/trunk/http-core/src/test/org/apache/http/util/TestCharArrayBuffer.java

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/impl/io/AbstractHttpDataReceiver.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/impl/io/AbstractHttpDataReceiver.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/impl/io/AbstractHttpDataReceiver.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/impl/io/AbstractHttpDataReceiver.java Sun Oct 23 11:20:46 2005
@@ -36,6 +36,7 @@
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
 import org.apache.http.util.ByteArrayBuffer;
+import org.apache.http.util.CharArrayBuffer;
 import org.apache.http.util.EncodingUtils;
 
 /**
@@ -57,6 +58,7 @@
     private ByteArrayBuffer linebuffer = null;
     
     private String charset = "US-ASCII";
+    private boolean ascii = true;
     
     protected void init(final InputStream instream, int buffersize) {
         if (instream == null) {
@@ -149,7 +151,10 @@
         return -1;
     }
     
-    public String readLine() throws IOException {
+    public int readLine(final CharArrayBuffer charbuffer) throws IOException {
+        if (charbuffer == null) {
+            throw new IllegalArgumentException("Char array buffer may not be null");
+        }
     	this.linebuffer.clear();
     	int noRead = 0;
         boolean retry = true;
@@ -160,7 +165,7 @@
                 // end of line found. 
                 if (this.linebuffer.isEmpty()) {
                     // the entire line is preset in the read buffer
-                    return lineFromReadBuffer(i);   
+                    return lineFromReadBuffer(charbuffer, i);
                 }
                 retry = false;
                 int len = i + 1 - this.bufferpos;
@@ -181,12 +186,12 @@
         }
         if (noRead == -1 && this.linebuffer.isEmpty()) {
             // indicate the end of stream
-            return null;
+            return -1;
         }
-        return lineFromLineBuffer();
+        return lineFromLineBuffer(charbuffer);
     }
     
-    private String lineFromLineBuffer() {
+    private int lineFromLineBuffer(final CharArrayBuffer charbuffer) {
         // discard LF if found
         int l = this.linebuffer.length(); 
         if (l > 0) {
@@ -202,11 +207,13 @@
                 }
             }
         }
-        return EncodingUtils.getString(
-                this.linebuffer.getBuffer(), 0, this.linebuffer.length(), this.charset);
+        copyToCharBuffer(
+                this.linebuffer.getBuffer(), 0, this.linebuffer.length(), 
+                charbuffer);
+        return this.linebuffer.length();
     }
     
-    private String lineFromReadBuffer(int pos) {
+    private int lineFromReadBuffer(final CharArrayBuffer charbuffer, int pos) {
         int off = this.bufferpos;
         int len;
         this.bufferpos = pos + 1;
@@ -215,11 +222,48 @@
             pos--;
         }
         len = pos - off;
-        return EncodingUtils.getString(this.buffer, off, len, this.charset);
+        copyToCharBuffer(this.buffer, off, len, charbuffer);
+        return len;
+    }
+    
+    private void copyToCharBuffer(final byte[] b, int off, int len, 
+            final CharArrayBuffer charbuffer) {
+        if (this.ascii) {
+            // this is an uuuuugly performance hack
+            charbuffer.ensureCapacity(len); 
+            int oldlen = charbuffer.length();
+            int newlen = oldlen + len;
+            charbuffer.setLength(newlen); 
+            char[] tmp = charbuffer.getBuffer();
+            for (int i = oldlen; i < newlen; i++) {
+                int ch = b[off + i]; 
+                if (ch < 0) {
+                    ch = 256 + ch;
+                }
+                tmp[i] = (char) ch;
+            }
+        } else {
+            String s = EncodingUtils.getString(b, off, len, this.charset);
+            charbuffer.ensureCapacity(s.length()); 
+            charbuffer.append(s);
+        }
+    }
+
+    public String readLine() throws IOException {
+        CharArrayBuffer charbuffer = new CharArrayBuffer(64);
+        int l = readLine(charbuffer);
+        if (l != -1) {
+            return charbuffer.toString();
+        } else {
+            return null;
+        }
     }
     
     public void reset(final HttpParams params) {
         this.charset = HttpProtocolParams.getHttpElementCharset(params);
+        this.ascii = 
+            this.charset.equalsIgnoreCase(EncodingUtils.ASCII_CHARSET) ||
+            this.charset.equalsIgnoreCase("ASCII");
     }
     
 }

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/io/HttpDataReceiver.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/io/HttpDataReceiver.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/io/HttpDataReceiver.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/io/HttpDataReceiver.java Sun Oct 23 11:20:46 2005
@@ -32,6 +32,7 @@
 import java.io.IOException;
 
 import org.apache.http.params.HttpParams;
+import org.apache.http.util.CharArrayBuffer;
 
 /**
  * <p>
@@ -51,6 +52,8 @@
     int read(byte[] b) throws IOException; 
     
     int read() throws IOException; 
+    
+    int readLine(CharArrayBuffer buffer) throws IOException;
     
     String readLine() throws IOException;
     

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/params/HttpProtocolParams.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/params/HttpProtocolParams.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/params/HttpProtocolParams.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/params/HttpProtocolParams.java Sun Oct 23 11:20:46 2005
@@ -30,6 +30,7 @@
 package org.apache.http.params;
 
 import org.apache.http.HttpVersion;
+import org.apache.http.util.EncodingUtils;
 
 /**
  * This class implements an adaptor around the {@link HttpParams} interface
@@ -184,7 +185,7 @@
         }
         String charset = (String) params.getParameter(HTTP_ELEMENT_CHARSET);
         if (charset == null) {
-            charset = "US-ASCII";
+            charset = EncodingUtils.ASCII_CHARSET;
         }
         return charset;
     }
@@ -211,7 +212,7 @@
         }
         String charset = (String) params.getParameter(HTTP_CONTENT_CHARSET);
         if (charset == null) {
-            charset = "ISO-8859-1";
+            charset = EncodingUtils.ISO_8859_1_CHARSET;
         }
         return charset;
     }

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/CharArrayBuffer.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/CharArrayBuffer.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/CharArrayBuffer.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/CharArrayBuffer.java Sun Oct 23 11:20:46 2005
@@ -128,6 +128,13 @@
         return this.len;
     }
 
+    public void ensureCapacity(int required) {
+        int available = this.buffer.length - this.len;
+        if (required > available) {
+            expand(this.len + required);
+        }
+    }
+    
     public void setLength(int len) {
         if (len < 0 || len > this.buffer.length) {
             throw new IndexOutOfBoundsException();

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EncodingUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EncodingUtils.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EncodingUtils.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EncodingUtils.java Sun Oct 23 11:20:46 2005
@@ -41,7 +41,10 @@
 public class EncodingUtils {
 
     /** ASCII chatset */
-    private static final String ASCII_CHARSET = "US-ASCII";
+    public static final String ASCII_CHARSET = "US-ASCII";
+    
+    /** ISO-8859-1 chatset */
+    public static final String ISO_8859_1_CHARSET = "ISO-8859-1";
     
     /**
      * Converts the byte array of HTTP content characters to a string. If

Modified: jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EntityUtils.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EntityUtils.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EntityUtils.java (original)
+++ jakarta/httpclient/trunk/http-core/src/java/org/apache/http/util/EntityUtils.java Sun Oct 23 11:20:46 2005
@@ -113,7 +113,7 @@
             charset = defaultCharset;
         }
         if (charset == null) {
-            charset = "ISO-8859-1";
+            charset = EncodingUtils.ISO_8859_1_CHARSET;
         }
         Reader reader = new InputStreamReader(entity.getContent(), charset);
         CharArrayBuffer buffer = new CharArrayBuffer(i); 

Modified: jakarta/httpclient/trunk/http-core/src/test/org/apache/http/impl/TestHttpDataReceiverAndTransmitter.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/test/org/apache/http/impl/TestHttpDataReceiverAndTransmitter.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/test/org/apache/http/impl/TestHttpDataReceiverAndTransmitter.java (original)
+++ jakarta/httpclient/trunk/http-core/src/test/org/apache/http/impl/TestHttpDataReceiverAndTransmitter.java Sun Oct 23 11:20:46 2005
@@ -41,6 +41,7 @@
 import org.apache.http.mockup.HttpDataTransmitterMockup;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.util.EncodingUtils;
 
 public class TestHttpDataReceiverAndTransmitter extends TestCase {
 
@@ -346,6 +347,42 @@
         }
         assertNull(receiver.readLine());
         assertNull(receiver.readLine());
+    }
+
+    public void testNonAsciiReadWriteLine() throws Exception {
+        String s1 = constructString(SWISS_GERMAN_HELLO);
+        
+        HttpParams params = new DefaultHttpParams(null);
+        HttpProtocolParams.setHttpElementCharset(params, EncodingUtils.ISO_8859_1_CHARSET);
+        
+        HttpDataTransmitterMockup transmitter = new HttpDataTransmitterMockup();
+        transmitter.reset(params);
+
+        for (int i = 0; i < 10; i++) {
+            transmitter.writeLine(s1);
+        }
+        transmitter.flush();
+        
+        HttpDataReceiverMockup receiver = new HttpDataReceiverMockup(
+                transmitter.getData());
+        HttpProtocolParams.setHttpElementCharset(params, EncodingUtils.ASCII_CHARSET);
+        receiver.reset(params);
+
+        for (int i = 0; i < 10; i++) {
+            assertEquals(s1, receiver.readLine());
+        }
+        assertNull(receiver.readLine());
+        assertNull(receiver.readLine());
+    }
+
+    public void testInvalidCharArrayBuffer() throws Exception {
+        HttpDataReceiverMockup receiver = new HttpDataReceiverMockup(new byte[] {});
+        try {
+            receiver.readLine(null); 
+            fail("IllegalArgumentException should have been thrown");
+        } catch (IllegalArgumentException ex) {
+            //expected
+        }
     }
     
 }

Modified: jakarta/httpclient/trunk/http-core/src/test/org/apache/http/util/TestCharArrayBuffer.java
URL: http://svn.apache.org/viewcvs/jakarta/httpclient/trunk/http-core/src/test/org/apache/http/util/TestCharArrayBuffer.java?rev=327828&r1=327827&r2=327828&view=diff
==============================================================================
--- jakarta/httpclient/trunk/http-core/src/test/org/apache/http/util/TestCharArrayBuffer.java (original)
+++ jakarta/httpclient/trunk/http-core/src/test/org/apache/http/util/TestCharArrayBuffer.java Sun Oct 23 11:20:46 2005
@@ -198,5 +198,13 @@
     		// expected
     	}
     }
-    
+
+    public void testEnsureCapacity() throws Exception {
+        CharArrayBuffer buffer = new CharArrayBuffer(4);
+        buffer.ensureCapacity(2);
+        assertEquals(4, buffer.capacity());
+        buffer.ensureCapacity(8);
+        assertEquals(8, buffer.capacity());
+    }
+        
 }