提交 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
<h1>Change Log</h1>
<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
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.
......
......@@ -23,9 +23,16 @@ public class StringUtils {
private static SoftReference<String[]> softCache =
new SoftReference<String[]>(null);
private static long softCacheCreated;
private static final char[] HEX = "0123456789abcdef".toCharArray();
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 {
for (int i = 0; i < HEX_DECODE.length; i++) {
HEX_DECODE[i] = -1;
......@@ -89,7 +96,20 @@ public class StringUtils {
* @return the uppercase text
*/
public static String toUpperEnglish(String s) {
return s.toUpperCase(Locale.ENGLISH);
if (s.length() > TO_UPPER_CACHE_MAX_ENTRY_LENGTH) {
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;
}
/**
......
......@@ -5,6 +5,7 @@
*/
package org.h2.test.unit;
import java.util.Locale;
import java.util.Random;
import org.h2.test.TestBase;
......@@ -31,12 +32,14 @@ public class TestStringCache extends TestBase {
*
* @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();
}
@Override
public void test() throws InterruptedException {
testToUpperToLower();
returnNew = true;
StringUtils.clearCache();
testSingleThread(getSize(5000, 20000));
......@@ -46,8 +49,62 @@ public class TestStringCache extends TestBase {
testSingleThread(getSize(5000, 20000));
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() {
testToUpperCache();
testToUpperCache();
testToUpperCache();
returnNew = false;
for (int i = 0; i < 6; i++) {
useIntern = (i % 2) == 0;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论