Skip to content

Commit fe4edac

Browse files
mdeinumfmbenhassine
authored andcommitted
Reduce the toCharArray overhead
Both the PatternMatcher and JdbcParameterUtils use String.toCharArray for processing. This will create a new char[] which needs to be collected. The same code has been rewritten to use String.charAt to reduce the overhead. Additionally unneeded object creation in the PatternMatcher has been removed as well, to reduce further objects needed to be gc'ed.
1 parent d9a360d commit fe4edac

File tree

2 files changed

+34
-43
lines changed

2 files changed

+34
-43
lines changed

spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JdbcParameterUtils.java

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
2727
*
2828
* @author Thomas Risberg
2929
* @author Juergen Hoeller
30+
* @author Marten Deinum
3031
* @since 2.0
3132
*/
3233
public class JdbcParameterUtils {
@@ -53,30 +54,29 @@ public static int countParameterPlaceholders(String sql, List<String> namedParam
5354
return 0;
5455
}
5556

56-
char[] statement = sql.toCharArray();
5757
boolean withinQuotes = false;
5858
Map<String, StringBuilder> namedParameters = new HashMap<>();
5959
char currentQuote = '-';
6060
int parameterCount = 0;
6161
int i = 0;
62-
while (i < statement.length) {
62+
while (i < sql.length()) {
6363
if (withinQuotes) {
64-
if (statement[i] == currentQuote) {
64+
if (sql.charAt(i) == currentQuote) {
6565
withinQuotes = false;
6666
currentQuote = '-';
6767
}
6868
}
6969
else {
70-
if (statement[i] == '"' || statement[i] == '\'') {
70+
if (sql.charAt(i) == '"' || sql.charAt(i) == '\'') {
7171
withinQuotes = true;
72-
currentQuote = statement[i];
72+
currentQuote = sql.charAt(i);
7373
}
7474
else {
75-
if (statement[i] == ':' || statement[i] == '&') {
75+
if (sql.charAt(i) == ':' || sql.charAt(i) == '&') {
7676
int j = i + 1;
7777
StringBuilder parameter = new StringBuilder();
78-
while (j < statement.length && parameterNameContinues(statement, j)) {
79-
parameter.append(statement[j]);
78+
while (j < sql.length() && parameterNameContinues(sql, j)) {
79+
parameter.append(sql.charAt(j));
8080
j++;
8181
}
8282
if (j - i > 1) {
@@ -88,7 +88,7 @@ public static int countParameterPlaceholders(String sql, List<String> namedParam
8888
}
8989
}
9090
else {
91-
if (statement[i] == '?') {
91+
if (sql.charAt(i) == '?') {
9292
parameterCount++;
9393
}
9494
}
@@ -108,10 +108,11 @@ public static int countParameterPlaceholders(String sql, List<String> namedParam
108108
* @param statement the SQL statement
109109
* @param pos the position within the statement
110110
*/
111-
private static boolean parameterNameContinues(char[] statement, int pos) {
112-
return (statement[pos] != ' ' && statement[pos] != ',' && statement[pos] != ')' &&
113-
statement[pos] != '"' && statement[pos] != '\'' && statement[pos] != '|' &&
114-
statement[pos] != ';' && statement[pos] != '\n' && statement[pos] != '\r');
111+
private static boolean parameterNameContinues(String statement, int pos) {
112+
char character = statement.charAt(pos);
113+
return (character != ' ' && character != ',' && character != ')' &&
114+
character != '"' && character != '\'' && character != '|' &&
115+
character != ';' && character != '\n' && character != '\r');
115116
}
116117

117118
}

spring-batch-infrastructure/src/main/java/org/springframework/batch/support/PatternMatcher.java

+19-29
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2007 the original author or authors.
2+
* Copyright 2006-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,9 +16,7 @@
1616
package org.springframework.batch.support;
1717

1818
import java.util.ArrayList;
19-
import java.util.Collections;
2019
import java.util.Comparator;
21-
import java.util.HashMap;
2220
import java.util.List;
2321
import java.util.Map;
2422

@@ -27,11 +25,12 @@
2725
/**
2826
* @author Dave Syer
2927
* @author Dan Garrette
28+
* @author Marten Deinum
3029
*/
3130
public class PatternMatcher<S> {
3231

33-
private Map<String, S> map = new HashMap<>();
34-
private List<String> sorted = new ArrayList<>();
32+
private final Map<String, S> map;
33+
private final List<String> sorted;
3534

3635
/**
3736
* Initialize a new {@link PatternMatcher} with a map of patterns to values
@@ -42,14 +41,7 @@ public PatternMatcher(Map<String, S> map) {
4241
this.map = map;
4342
// Sort keys to start with the most specific
4443
sorted = new ArrayList<>(map.keySet());
45-
Collections.sort(sorted, new Comparator<String>() {
46-
@Override
47-
public int compare(String o1, String o2) {
48-
String s1 = o1; // .replace('?', '{');
49-
String s2 = o2; // .replace('*', '}');
50-
return s2.compareTo(s1);
51-
}
52-
});
44+
sorted.sort(Comparator.reverseOrder());
5345
}
5446

5547
/**
@@ -66,12 +58,10 @@ public int compare(String o1, String o2) {
6658
* <code>false</code> otherwise.
6759
*/
6860
public static boolean match(String pattern, String str) {
69-
char[] patArr = pattern.toCharArray();
70-
char[] strArr = str.toCharArray();
7161
int patIdxStart = 0;
72-
int patIdxEnd = patArr.length - 1;
62+
int patIdxEnd = pattern.length() - 1;
7363
int strIdxStart = 0;
74-
int strIdxEnd = strArr.length - 1;
64+
int strIdxEnd = str.length() - 1;
7565
char ch;
7666

7767
boolean containsStar = pattern.contains("*");
@@ -82,9 +72,9 @@ public static boolean match(String pattern, String str) {
8272
return false; // Pattern and string do not have the same size
8373
}
8474
for (int i = 0; i <= patIdxEnd; i++) {
85-
ch = patArr[i];
75+
ch = pattern.charAt(i);
8676
if (ch != '?') {
87-
if (ch != strArr[i]) {
77+
if (ch != str.charAt(i)) {
8878
return false;// Character mismatch
8979
}
9080
}
@@ -97,9 +87,9 @@ public static boolean match(String pattern, String str) {
9787
}
9888

9989
// Process characters before first star
100-
while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
90+
while ((ch = pattern.charAt(patIdxStart)) != '*' && strIdxStart <= strIdxEnd) {
10191
if (ch != '?') {
102-
if (ch != strArr[strIdxStart]) {
92+
if (ch != str.charAt(strIdxStart)) {
10393
return false;// Character mismatch
10494
}
10595
}
@@ -110,17 +100,17 @@ public static boolean match(String pattern, String str) {
110100
// All characters in the string are used. Check if only '*'s are
111101
// left in the pattern. If so, we succeeded. Otherwise failure.
112102
for (int i = patIdxStart; i <= patIdxEnd; i++) {
113-
if (patArr[i] != '*') {
103+
if (pattern.charAt(i) != '*') {
114104
return false;
115105
}
116106
}
117107
return true;
118108
}
119109

120110
// Process characters after last star
121-
while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
111+
while ((ch = pattern.charAt(patIdxEnd)) != '*' && strIdxStart <= strIdxEnd) {
122112
if (ch != '?') {
123-
if (ch != strArr[strIdxEnd]) {
113+
if (ch != str.charAt(strIdxEnd)) {
124114
return false;// Character mismatch
125115
}
126116
}
@@ -131,7 +121,7 @@ public static boolean match(String pattern, String str) {
131121
// All characters in the string are used. Check if only '*'s are
132122
// left in the pattern. If so, we succeeded. Otherwise failure.
133123
for (int i = patIdxStart; i <= patIdxEnd; i++) {
134-
if (patArr[i] != '*') {
124+
if (pattern.charAt(i) != '*') {
135125
return false;
136126
}
137127
}
@@ -143,7 +133,7 @@ public static boolean match(String pattern, String str) {
143133
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
144134
int patIdxTmp = -1;
145135
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
146-
if (patArr[i] == '*') {
136+
if (pattern.charAt(i) == '*') {
147137
patIdxTmp = i;
148138
break;
149139
}
@@ -160,9 +150,9 @@ public static boolean match(String pattern, String str) {
160150
int foundIdx = -1;
161151
strLoop: for (int i = 0; i <= strLength - patLength; i++) {
162152
for (int j = 0; j < patLength; j++) {
163-
ch = patArr[patIdxStart + j + 1];
153+
ch = pattern.charAt(patIdxStart + j + 1);
164154
if (ch != '?') {
165-
if (ch != strArr[strIdxStart + i + j]) {
155+
if (ch != str.charAt(strIdxStart + i + j)) {
166156
continue strLoop;
167157
}
168158
}
@@ -183,7 +173,7 @@ public static boolean match(String pattern, String str) {
183173
// All characters in the string are used. Check if only '*'s are left
184174
// in the pattern. If so, we succeeded. Otherwise failure.
185175
for (int i = patIdxStart; i <= patIdxEnd; i++) {
186-
if (patArr[i] != '*') {
176+
if (pattern.charAt(i) != '*') {
187177
return false;
188178
}
189179
}

0 commit comments

Comments
 (0)