Hello.
Can anybody hear me? I'd like to talk to someone who cares about String,
StringBuffer and StringBuilder. I am NetBeans Platform architect and I'd like
to use this opportunity to fasten start of NetBeans as well as improve OpenJDK
project. Here is my story:
I've been investigating the memory allocations during NetBeans start. I've
noticed that we are allocating about 60MB of char[] mostly due to parsing of
various configuration files. Suprisingly at least half of these 60MB is
garbage collected quickly. This is because we use StringBuffer/Builder to
concatenate the texts and then convert them to String. The conversion to
String however allocates new array. I believe this is less then optimal.
However there is no way I can tell the Java libraries to be more effective.
That is why I decided to create my patch. It adds StringBuffer.build() method
which can create Strings without unnecessary copying. It adds
StringBuilder.build() method too, for symetry, but that one is not that
effective (I don't know how to make it robust without usage of
synchronization). If I had StringBuffer.build, I could allocate only 30MB of
data on NetBeans startup and very likely make it faster. Can you consider
adding this method to JDK7?
I am attaching my patch that adds the new API. I can refine it, add new tests,
etc. I just need a buddy interested in StringBuffer to guide me. I belive that
together we can make NetBeans start faster and OpenJDK7 better. Can you help
me?
-jt
diff -r a661d8587b5d src/share/classes/java/lang/AbstractStringBuilder.java
--- a/src/share/classes/java/lang/AbstractStringBuilder.java Wed Dec 08 00:35:33 2010 -0800
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java Wed Dec 08 22:04:11 2010 +0100
@@ -872,6 +872,17 @@
throw new StringIndexOutOfBoundsException(end - start);
return new String(value, start, end - start);
}
+
+ /** Converts content of this builder into {...@link String} representation
+ * and empties the builder.
+ * @return the string representation of the characters inside this builder
+ * @since 1.7
+ */
+ public String build() {
+ String s = toString();
+ count = 0;
+ return s;
+ }
/**
* Inserts the string representation of a subarray of the {...@code str}
diff -r a661d8587b5d src/share/classes/java/lang/String.java
--- a/src/share/classes/java/lang/String.java Wed Dec 08 00:35:33 2010 -0800
+++ b/src/share/classes/java/lang/String.java Wed Dec 08 22:04:11 2010 +0100
@@ -219,6 +219,9 @@
* characters outside the bounds of the {...@code value} array
*/
public String(char value[], int offset, int count) {
+ this(value, offset, count, true);
+ }
+ String(char value[], int offset, int count, boolean copy) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
@@ -229,9 +232,15 @@
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
- this.offset = 0;
- this.count = count;
- this.value = Arrays.copyOfRange(value, offset, offset+count);
+ if (copy) {
+ this.offset = 0;
+ this.count = count;
+ this.value = Arrays.copyOfRange(value, offset, offset+count);
+ } else {
+ this.value = value;
+ this.offset = offset;
+ this.count = count;
+ }
}
/**
diff -r a661d8587b5d src/share/classes/java/lang/StringBuffer.java
--- a/src/share/classes/java/lang/StringBuffer.java Wed Dec 08 00:35:33 2010 -0800
+++ b/src/share/classes/java/lang/StringBuffer.java Wed Dec 08 22:04:11 2010 +0100
@@ -411,6 +411,21 @@
public synchronized String substring(int start, int end) {
return super.substring(start, end);
}
+
+ /** Copies content of this buffer into a string and empties the buffer.
+ * The implementation reuses the char array without copying. As such,
+ * if the initial capacity of the buffer was properly specified, one
+ * can create {...@link String} effectively, without any array copying.
+ * @return string representing content of this buffer
+ * @since 1.7
+ */
+ @Override
+ public synchronized String build() {
+ String s = new String(value, 0, count, false);
+ value = new char[0];
+ count = 0;
+ return s;
+ }
/**
* @throws StringIndexOutOfBoundsException {...@inheritdoc}