Skip to content

Instantly share code, notes, and snippets.

@odrotbohm
Created September 10, 2012 16:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odrotbohm/3691774 to your computer and use it in GitHub Desktop.
Save odrotbohm/3691774 to your computer and use it in GitHub Desktop.
Test case to show String.substring(int) performance issue for Java 7u06 and later.
/**
* Test class to show a huge performance dump in Java 7u06/u07 for the {@link String#substring(int)} compared to
* {@link String#substring(int, int)}. On versions before 7u06 I get numbers like 23ms for the first method call and
* 12ms for the second. On update 6 and 7 I get 10483ms for the first call, 16ms for the second.
* <p>
* The issue seems to be related to a fix in related to {@code Arrays.copyOnWrite} (this is the hotspot the profiler
* unveiled) introduced with update 6 (see links below).
* <p>
* Feel free to add your numbers in the comments below.
*
* @see http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-May/010257.html
* @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7174363
* @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=2226462
* @author Oliver Gierke
*/
public class Test {
public static void main(String... args) throws Exception {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 1000 * 100; i++) {
builder.append(" ");
}
String source = builder.toString();
long before = System.currentTimeMillis();
criticalCode(source);
long after = System.currentTimeMillis();
System.out.println(String.format("%sms", after - before));
before = System.currentTimeMillis();
criticalCode2(source);
after = System.currentTimeMillis();
System.out.println(String.format("%sms", after - before));
}
private static void criticalCode(String value) {
for (int i = 0; i < value.length(); i++) {
value.substring(i);
}
}
private static void criticalCode2(String value) {
for (int i = 0; i < value.length(); i++) {
value.substring(i, i + 1);
}
}
}
@hygl
Copy link

hygl commented Sep 11, 2012

value.substring(i); and value.substring(i, i + 1); do different things, it should be value.substring(i, value.length()); , that has unfortunatly the same bad performance in java 7u06.

@odrotbohm
Copy link
Author

Good point. In the case of the ResourceDatabasePopulator we're actually only interested in the next character (or the next few) as we're testing for a dilimiter but I think the current code was written as is as you don't have to deal with potential out-of-range cases.

@pidster
Copy link

pidster commented Sep 11, 2012

@hygl isn't the comparison between criticalCode on < 7u06 and 7u06+, rather than between criticalCode and criticalCode2?

@hygl
Copy link

hygl commented Sep 11, 2012

@pidster I know, I initialy reported it. https://jira.springsource.org/browse/SPR-9781 Only wanted to let Oliver know, that the latter is not in any case a replacement for the former.

@codylerum
Copy link

Just ran into this after upgrading an ubuntu server to 7u7.

2802ms was 5ms
7ms was 3ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment