/* * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, and the * EPL 1.0 (http://h2database.com/html/license.html). Initial Developer: H2 * Group */ package org.h2.test.unit; import java.util.Locale; import java.util.Random; import java.util.concurrent.TimeUnit; import org.h2.test.TestBase; import org.h2.util.StringUtils; /** * Tests the string cache facility. */ public class TestStringCache extends TestBase { /** * Flag to indicate the test should stop. */ volatile boolean stop; private final Random random = new Random(1); private final String[] some = { null, "", "ABC", "this is a medium sized string", "1", "2" }; private boolean useIntern; /** * This method is called when executing this application from the command * line. * * @param args the command line parameters */ public static void main(String... args) throws Exception { TestBase.createCaller().init().test(); new TestStringCache().runBenchmark(); } @Override public void test() throws InterruptedException { testToUpperToLower(); StringUtils.clearCache(); 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.nanoTime(); for (int a = 0; a < repeat; a++) { for (String x : test) { String y = StringUtils.toUpperEnglish(x); testLen += y.length(); } } time = System.nanoTime() - time; System.out.println("cache " + TimeUnit.NANOSECONDS.toMillis(time)); time = System.nanoTime(); for (int a = 0; a < repeat; a++) { for (String x : test) { String y = x.toUpperCase(Locale.ENGLISH); testLen -= y.length(); } } time = System.nanoTime() - time; System.out.println("toUpperCase " + TimeUnit.NANOSECONDS.toMillis(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(); for (int i = 0; i < 6; i++) { useIntern = (i % 2) == 0; long time = System.nanoTime(); testSingleThread(100000); time = System.nanoTime() - time; System.out.println(TimeUnit.NANOSECONDS.toMillis(time) + " ms (useIntern=" + useIntern + ")"); } } private String randomString() { if (random.nextBoolean()) { String s = some[random.nextInt(some.length)]; if (s != null && random.nextBoolean()) { s = new String(s); } return s; } int len = random.nextBoolean() ? random.nextInt(1000) : random.nextInt(10); StringBuilder buff = new StringBuilder(len); for (int i = 0; i < len; i++) { buff.append(random.nextInt(0xfff)); } return buff.toString(); } /** * Test one string operation using the string cache. */ void testString() { String a = randomString(); String b; if (useIntern) { b = a == null ? null : a.intern(); } else { b = StringUtils.cache(a); } try { assertEquals(a, b); } catch (Exception e) { TestBase.logError("error", e); } } private void testSingleThread(int len) { for (int i = 0; i < len; i++) { testString(); } } private void testMultiThreads() throws InterruptedException { int threadCount = getSize(3, 100); Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { Thread t = new Thread(new Runnable() { @Override public void run() { while (!stop) { testString(); } } }); threads[i] = t; } for (int i = 0; i < threadCount; i++) { threads[i].start(); } int wait = getSize(200, 2000); Thread.sleep(wait); stop = true; for (int i = 0; i < threadCount; i++) { threads[i].join(); } } }