Work around JDK7 String#substring performance regression
String#substring has become significantly slower as of JDK 1.7.0_06 [1], such that there are performance degradations by a factor of 100-1000 in ResourceDatabasePopulator, especially for large SQL files. This commit works around this problem by minimizing the substring scope to the least amount possible to prevent unnecessary internal copying of strings (which seems to cause the issue). [1]: http://mail.openjdk.java.net/pipermail/core-libs-dev/2012-May/010257.html Issue: SPR-9781
This commit is contained in:
committed by
Chris Beams
parent
dfe05305e2
commit
3fb3b7d67a
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,6 +43,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Oliver Gierke
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||
@@ -265,7 +266,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||
if (content[i] == '\'') {
|
||||
inLiteral = !inLiteral;
|
||||
}
|
||||
if (!inLiteral && script.substring(i).startsWith(delim)) {
|
||||
if (!inLiteral && startsWithDelimiter(script, i, delim)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -273,8 +274,29 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an SQL script into separate statements delimited with the provided delimiter character.
|
||||
* Each individual statement will be added to the provided <code>List</code>.
|
||||
* Return whether the substring of a given source {@link String} starting at the
|
||||
* given index starts with the given delimiter.
|
||||
*
|
||||
* @param source the source {@link String} to inspect
|
||||
* @param startIndex the index to look for the delimiter
|
||||
* @param delim the delimiter to look for
|
||||
*/
|
||||
private boolean startsWithDelimiter(String source, int startIndex, String delim) {
|
||||
|
||||
int endIndex = startIndex + delim.length();
|
||||
|
||||
if (source.length() < endIndex) {
|
||||
// String is too short to contain the delimiter
|
||||
return false;
|
||||
}
|
||||
|
||||
return source.substring(startIndex, endIndex).equals(delim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Split an SQL script into separate statements delimited with the provided delimiter
|
||||
* character. Each individual statement will be added to the provided {@code List}.
|
||||
*
|
||||
* @param script the SQL script
|
||||
* @param delim character delimiting each statement (typically a ';' character)
|
||||
* @param statements the List that will contain the individual statements
|
||||
@@ -301,7 +323,7 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
|
||||
inLiteral = !inLiteral;
|
||||
}
|
||||
if (!inLiteral) {
|
||||
if (script.substring(i).startsWith(delim)) {
|
||||
if (startsWithDelimiter(script, i, delim)) {
|
||||
if (sb.length() > 0) {
|
||||
statements.add(sb.toString());
|
||||
sb = new StringBuilder();
|
||||
|
||||
Reference in New Issue
Block a user