Created
September 10, 2012 16:06
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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); | |
} | |
} | |
} |
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.
@hygl isn't the comparison between criticalCode on < 7u06 and 7u06+, rather than between criticalCode and criticalCode2?
@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.
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
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.