提交 8021286e authored 作者: Thomas Mueller's avatar Thomas Mueller

StringUtils.toUpperEnglish now has a small cache. This should speed up reading…

StringUtils.toUpperEnglish now has a small cache. This should speed up reading from a ResultSet when using the column name.
上级 0ff58e70
...@@ -17,7 +17,9 @@ Change Log ...@@ -17,7 +17,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>MVStore: up to 65535 open transactions are now supported. <ul><li>StringUtils.toUpperEnglish now has a small cache.
This should speed up reading from a ResultSet when using the column name.
</li><li>MVStore: up to 65535 open transactions are now supported.
Previously, the limit was at most 65535 transactions between the oldest open and the Previously, the limit was at most 65535 transactions between the oldest open and the
newest open transaction (which was quite a strange limit). newest open transaction (which was quite a strange limit).
</li><li>The default limit for in-place LOB objects was changed from 128 to 256 bytes. </li><li>The default limit for in-place LOB objects was changed from 128 to 256 bytes.
......
...@@ -23,9 +23,16 @@ public class StringUtils { ...@@ -23,9 +23,16 @@ public class StringUtils {
private static SoftReference<String[]> softCache = private static SoftReference<String[]> softCache =
new SoftReference<String[]>(null); new SoftReference<String[]>(null);
private static long softCacheCreated; private static long softCacheCreated;
private static final char[] HEX = "0123456789abcdef".toCharArray(); private static final char[] HEX = "0123456789abcdef".toCharArray();
private static final int[] HEX_DECODE = new int['f' + 1]; private static final int[] HEX_DECODE = new int['f' + 1];
// memory used by this cache:
// 4 * 1024 * 2 (strings per pair) * 64 * 2 (bytes per char) = 0.5 MB
private static final int TO_UPPER_CACHE_LENGTH = 2 * 1024;
private static final int TO_UPPER_CACHE_MAX_ENTRY_LENGTH = 64;
private static final String[][] TO_UPPER_CACHE = new String[TO_UPPER_CACHE_LENGTH][];
static { static {
for (int i = 0; i < HEX_DECODE.length; i++) { for (int i = 0; i < HEX_DECODE.length; i++) {
HEX_DECODE[i] = -1; HEX_DECODE[i] = -1;
...@@ -89,8 +96,21 @@ public class StringUtils { ...@@ -89,8 +96,21 @@ public class StringUtils {
* @return the uppercase text * @return the uppercase text
*/ */
public static String toUpperEnglish(String s) { public static String toUpperEnglish(String s) {
if (s.length() > TO_UPPER_CACHE_MAX_ENTRY_LENGTH) {
return s.toUpperCase(Locale.ENGLISH); return s.toUpperCase(Locale.ENGLISH);
} }
int index = s.hashCode() & (TO_UPPER_CACHE_LENGTH - 1);
String[] e = TO_UPPER_CACHE[index];
if (e != null) {
if (e[0].equals(s)) {
return e[1];
}
}
String s2 = s.toUpperCase(Locale.ENGLISH);
e = new String[] { s, s2 };
TO_UPPER_CACHE[index] = e;
return s2;
}
/** /**
* Convert a string to lowercase using the English locale. * Convert a string to lowercase using the English locale.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
package org.h2.test.unit; package org.h2.test.unit;
import java.util.Locale;
import java.util.Random; import java.util.Random;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -31,12 +32,14 @@ public class TestStringCache extends TestBase { ...@@ -31,12 +32,14 @@ public class TestStringCache extends TestBase {
* *
* @param args the command line parameters * @param args the command line parameters
*/ */
public static void main(String... args) { public static void main(String... args) throws Exception {
TestBase.createCaller().init().test();
new TestStringCache().runBenchmark(); new TestStringCache().runBenchmark();
} }
@Override @Override
public void test() throws InterruptedException { public void test() throws InterruptedException {
testToUpperToLower();
returnNew = true; returnNew = true;
StringUtils.clearCache(); StringUtils.clearCache();
testSingleThread(getSize(5000, 20000)); testSingleThread(getSize(5000, 20000));
...@@ -47,7 +50,61 @@ public class TestStringCache extends TestBase { ...@@ -47,7 +50,61 @@ public class TestStringCache extends TestBase {
testMultiThreads(); testMultiThreads();
} }
private void testToUpperCache() {
Random r = new Random();
String[] test = new String[50];
for (int i = 0; i < test.length; i++) {
StringBuilder buff = new StringBuilder();
for (int a = 0; a < 50; a++) {
buff.append((char) r.nextInt());
}
String a = buff.toString();
test[i] = a;
}
int repeat = 100000;
int testLen = 0;
long time = System.currentTimeMillis();
for (int a = 0; a < repeat; a++) {
for (String x : test) {
String y = StringUtils.toUpperEnglish(x);
testLen += y.length();
}
}
time = System.currentTimeMillis() - time;
System.out.println("cache " + time);
time = System.currentTimeMillis();
for (int a = 0; a < repeat; a++) {
for (String x : test) {
String y = x.toUpperCase(Locale.ENGLISH);
testLen -= y.length();
}
}
time = System.currentTimeMillis() - time;
System.out.println("toUpperCase " + time);
assertEquals(0, testLen);
}
private void testToUpperToLower() {
Random r = new Random();
for (int i = 0; i < 1000; i++) {
StringBuilder buff = new StringBuilder();
for (int a = 0; a < 100; a++) {
buff.append((char) r.nextInt());
}
String a = buff.toString();
String b = StringUtils.toUpperEnglish(a);
String c = a.toUpperCase(Locale.ENGLISH);
assertEquals(c, b);
String d = StringUtils.toLowerEnglish(a);
String e = a.toLowerCase(Locale.ENGLISH);
assertEquals(e, d);
}
}
private void runBenchmark() { private void runBenchmark() {
testToUpperCache();
testToUpperCache();
testToUpperCache();
returnNew = false; returnNew = false;
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
useIntern = (i % 2) == 0; useIntern = (i % 2) == 0;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论