Patch: StringBuffer optimization

Anthony Green green@cygnus.com
Sat Apr 8 21:46:00 GMT 2000


Profiling the Embedded CaffeineMark is very educational.  It points
out an obvious opportunity to eliminate many costly calls to
_Jv_MonitorEnter/_Jv_MonitorExit.

I've also replaced a call to java.lang.Math.max.


2000-04-08  Anthony Green  <green@cygnus.com>

	* java/lang/StringBuffer.java (ensureCapacity): Don't call Math::max.
	(ensureCapacity_unsynchronized): New private method.
	(append): Use ensureCapacity_unsynchronized.

Index: libjava/java/lang/StringBuffer.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/StringBuffer.java,v
retrieving revision 1.3
diff -c -r1.3 StringBuffer.java
*** StringBuffer.java	2000/01/17 00:00:43	1.3
--- StringBuffer.java	2000/04/09 04:39:07
***************
*** 28,34 ****
  
    public synchronized StringBuffer append (char ch)
      {
!       ensureCapacity (count + 1);
        value[count++] = ch;
        return this;
      }
--- 28,34 ----
  
    public synchronized StringBuffer append (char ch)
      {
!       ensureCapacity_unsynchronized (count + 1);
        value[count++] = ch;
        return this;
      }
***************
*** 63,69 ****
        if (str == null)
  	str = "null";
        int len = str.length();
!       ensureCapacity (count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
--- 63,69 ----
        if (str == null)
  	str = "null";
        int len = str.length();
!       ensureCapacity_unsynchronized (count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
***************
*** 76,82 ****
  
    public synchronized StringBuffer append (char[] data, int offset, int count)
      {
!       ensureCapacity (this.count + count);
        System.arraycopy(data, offset, value, this.count, count);
        this.count += count;
        return this;
--- 76,82 ----
  
    public synchronized StringBuffer append (char[] data, int offset, int count)
      {
!       ensureCapacity_unsynchronized (this.count + count);
        System.arraycopy(data, offset, value, this.count, count);
        this.count += count;
        return this;
***************
*** 104,110 ****
  	  int max = (minimumCapacity > value.length
  		     ? value.length*2+2
  		     : value.length);
! 	  minimumCapacity = Math.max(minimumCapacity, max);
  	  char[] nb = new char[minimumCapacity];
  	  System.arraycopy(value, 0, nb, 0, count);
  	  value = nb;
--- 104,110 ----
  	  int max = (minimumCapacity > value.length
  		     ? value.length*2+2
  		     : value.length);
! 	  minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
  	  char[] nb = new char[minimumCapacity];
  	  System.arraycopy(value, 0, nb, 0, count);
  	  value = nb;
***************
*** 112,117 ****
--- 112,137 ----
  	}
      }
  
+   // ensureCapacity is used by several synchronized methods in StringBuffer.
+   // There's no need to synchronize again.
+   private void ensureCapacity_unsynchronized (int minimumCapacity)
+     {
+       if (shared || minimumCapacity > value.length)
+ 	{
+ 	  // We don't want to make a larger vector when `shared' is
+ 	  // set.  If we do, then setLength becomes very inefficient
+ 	  // when repeatedly reusing a StringBuffer in a loop.
+ 	  int max = (minimumCapacity > value.length
+ 		     ? value.length*2+2
+ 		     : value.length);
+ 	  minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+ 	  char[] nb = new char[minimumCapacity];
+ 	  System.arraycopy(value, 0, nb, 0, count);
+ 	  value = nb;
+ 	  shared = false;
+ 	}
+     }
+ 
    public synchronized void getChars (int srcOffset, int srcEnd,
  				     char[] dst, int dstOffset)
      {
***************
*** 132,138 ****
      {
        if (offset < 0 || offset > count)
  	throw new StringIndexOutOfBoundsException (offset);
!       ensureCapacity (count+1);
        System.arraycopy(value, offset, value, offset+1, count-offset);
        value[offset] = ch;
        count++;
--- 152,158 ----
      {
        if (offset < 0 || offset > count)
  	throw new StringIndexOutOfBoundsException (offset);
!       ensureCapacity_unsynchronized (count+1);
        System.arraycopy(value, offset, value, offset+1, count-offset);
        value[offset] = ch;
        count++;
***************
*** 172,178 ****
        if (str == null)
  	str = "null";
        int len = str.length();
!       ensureCapacity(count+len);
        System.arraycopy(value, offset, value, offset+len, count-offset);
        str.getChars(0, len, value, offset);
        count += len;
--- 192,198 ----
        if (str == null)
  	str = "null";
        int len = str.length();
!       ensureCapacity_unsynchronized (count+len);
        System.arraycopy(value, offset, value, offset+len, count-offset);
        str.getChars(0, len, value, offset);
        count += len;
***************
*** 184,190 ****
        if (offset < 0 || offset > count)
  	throw new StringIndexOutOfBoundsException (offset);
        int len = data.length;
!       ensureCapacity (count+len);
        System.arraycopy(value, offset, value, offset+len, count-offset);
        System.arraycopy(data, 0, value, offset, len);
        count += len;
--- 204,210 ----
        if (offset < 0 || offset > count)
  	throw new StringIndexOutOfBoundsException (offset);
        int len = data.length;
!       ensureCapacity_unsynchronized (count+len);
        System.arraycopy(value, offset, value, offset+len, count-offset);
        System.arraycopy(data, 0, value, offset, len);
        count += len;
***************
*** 212,218 ****
        if (index < 0 || index >= count)
  	throw new StringIndexOutOfBoundsException (index);
        // Call ensureCapacity to enforce copy-on-write.
!       ensureCapacity (count);
        value[index] = ch;
      }
  
--- 232,238 ----
        if (index < 0 || index >= count)
  	throw new StringIndexOutOfBoundsException (index);
        // Call ensureCapacity to enforce copy-on-write.
!       ensureCapacity_unsynchronized (count);
        value[index] = ch;
      }
  
***************
*** 221,227 ****
        if (newLength < 0)
  	throw new StringIndexOutOfBoundsException (newLength);
  
!       ensureCapacity (newLength);
        for (int i = count; i < newLength; ++i)
  	value[i] = '\0';
        count = newLength;
--- 241,247 ----
        if (newLength < 0)
  	throw new StringIndexOutOfBoundsException (newLength);
  
!       ensureCapacity_unsynchronized (newLength);
        for (int i = count; i < newLength; ++i)
  	value[i] = '\0';
        count = newLength;


More information about the Java-patches mailing list