diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-28 17:54:57 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-03-28 17:54:57 +0000 |
commit | eb3451793aaf42870e44281708ccac51c010e837 (patch) | |
tree | 51c5f3646653b5153a74a2828b2af20c41cbd8d1 /icu4j/perf-tests/src/main/java/com | |
parent | e710c4fbd23e1b7d97da0a88a8499326861ad250 (diff) | |
parent | 8144ba71b4efcfe46cd0e76e85d371bcc7d55567 (diff) | |
download | icu-eb3451793aaf42870e44281708ccac51c010e837.tar.gz |
Snap for 11641499 from 8144ba71b4efcfe46cd0e76e85d371bcc7d55567 to build-tools-release
Change-Id: Ic926bb7ff166e37b678ae2768581ebec18fcea4a
Diffstat (limited to 'icu4j/perf-tests/src/main/java/com')
12 files changed, 5009 insertions, 0 deletions
diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/BreakIteratorPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/BreakIteratorPerformanceTest.java new file mode 100644 index 000000000..ee4530360 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/BreakIteratorPerformanceTest.java @@ -0,0 +1,196 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + ********************************************************************** + * Copyright (c) 2002-2008, International Business Machines * + * Corporation and others. All Rights Reserved. * + ********************************************************************** + */ +package com.ibm.icu.dev.test.perf; + +import java.io.FileInputStream; +import java.util.ArrayList; + +public class BreakIteratorPerformanceTest extends PerfTest { + + String fileContents; + + com.ibm.icu.text.BreakIterator iSentenceIter; + com.ibm.icu.text.BreakIterator iWordIter; + com.ibm.icu.text.BreakIterator iLineIter; + com.ibm.icu.text.BreakIterator iCharacterIter; + java.text.BreakIterator jSentenceIter; + java.text.BreakIterator jWordIter; + java.text.BreakIterator jLineIter; + java.text.BreakIterator jCharacterIter; + String[] iSentences; + String[] iWords; + String[] iLines; + String[] iCharacters; + String[] jSentences; + String[] jWords; + String[] jLines; + String[] jCharacters; + + public static void main(String[] args) throws Exception { + new BreakIteratorPerformanceTest().run(args); + } + + protected void setup(String[] args) { + try { + // read in the input file, being careful with a possible BOM + FileInputStream in = new FileInputStream(fileName); + BOMFreeReader reader = new BOMFreeReader(in, encoding); + fileContents = new String(readToEOS(reader)); + + // // get rid of any characters that may cause differences between ICU4J and Java BreakIterator + // // fileContents = fileContents.replaceAll("[\t\f\r\n\\-/ ]+", " "); + // String res = ""; + // StringTokenizer tokenizer = new StringTokenizer(fileContents, "\t\f\r\n-/ "); + // while (tokenizer.hasMoreTokens()) + // res += tokenizer.nextToken() + " "; + // fileContents = res.trim(); + + // create the break iterators with respect to locale + if (locale == null) { + iSentenceIter = com.ibm.icu.text.BreakIterator.getSentenceInstance(); + iWordIter = com.ibm.icu.text.BreakIterator.getWordInstance(); + iLineIter = com.ibm.icu.text.BreakIterator.getLineInstance(); + iCharacterIter = com.ibm.icu.text.BreakIterator.getCharacterInstance(); + + jSentenceIter = java.text.BreakIterator.getSentenceInstance(); + jWordIter = java.text.BreakIterator.getWordInstance(); + jLineIter = java.text.BreakIterator.getLineInstance(); + jCharacterIter = java.text.BreakIterator.getCharacterInstance(); + } else { + iSentenceIter = com.ibm.icu.text.BreakIterator.getSentenceInstance(locale); + iWordIter = com.ibm.icu.text.BreakIterator.getWordInstance(locale); + iLineIter = com.ibm.icu.text.BreakIterator.getLineInstance(locale); + iCharacterIter = com.ibm.icu.text.BreakIterator.getCharacterInstance(locale); + + jSentenceIter = java.text.BreakIterator.getSentenceInstance(locale); + jWordIter = java.text.BreakIterator.getWordInstance(locale); + jLineIter = java.text.BreakIterator.getLineInstance(locale); + jCharacterIter = java.text.BreakIterator.getCharacterInstance(locale); + } + + iSentences = init(iSentenceIter); + iWords = init(iWordIter); + iLines = init(iLineIter); + iCharacters = init(iCharacterIter); + jSentences = init(jSentenceIter); + jWords = init(jWordIter); + jLines = init(jLineIter); + jCharacters = init(jCharacterIter); + + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + + // we created some heavy objects, so lets try to clean up a little before running the tests + gc(); + } + + private String[] init(com.ibm.icu.text.BreakIterator iter) { + // set the string to iterate on + iter.setText(fileContents); + + // produce a token list + ArrayList tokenList = new ArrayList(); + int start = iter.first(); + for (int end = iter.next(); end != com.ibm.icu.text.BreakIterator.DONE; start = end, end = iter.next()) + tokenList.add(fileContents.substring(start, end)); + + // return the token list as a string array + return (String[]) tokenList.toArray(new String[0]); + } + + private String[] init(java.text.BreakIterator iter) { + // set the string to iterate on + iter.setText(fileContents); + + // produce a token list + ArrayList tokenList = new ArrayList(); + int start = iter.first(); + for (int end = iter.next(); end != com.ibm.icu.text.BreakIterator.DONE; start = end, end = iter.next()) + tokenList.add(fileContents.substring(start, end)); + + // return the token list as a string array + return (String[]) tokenList.toArray(new String[0]); + } + + PerfTest.Function createTestICU(final com.ibm.icu.text.BreakIterator iIter, final String[] correct, + final String breakType) { + return new PerfTest.Function() { + public void call() { + int k = 0; + int start = iIter.first(); + for (int end = iIter.next(); end != com.ibm.icu.text.BreakIterator.DONE; start = end, end = iIter + .next()) + if (!correct[k++].equals(fileContents.substring(start, end))) + throw new RuntimeException("ICU4J BreakIterator gave the wrong answer for " + breakType + " " + + (k - 1) + " during the performance test. Cannot continue the performance test."); + if (k != correct.length) + throw new RuntimeException("ICU4J BreakIterator gave the wrong number of " + breakType + + "s during the performance test. Cannot continue the performance test."); + } + + public long getOperationsPerIteration() { + return fileContents.length(); + } + }; + } + + PerfTest.Function createTestJava(final java.text.BreakIterator jIter, final String[] correct, final String breakType) { + return new PerfTest.Function() { + public void call() { + int k = 0; + int start = jIter.first(); + for (int end = jIter.next(); end != java.text.BreakIterator.DONE; start = end, end = jIter.next()) + if (!correct[k++].equals(fileContents.substring(start, end))) + throw new RuntimeException("Java BreakIterator gave the wrong answer for " + breakType + " " + + (k - 1) + " during the performance test. Cannot continue the performance test."); + if (k != correct.length) + throw new RuntimeException("Java BreakIterator gave the wrong number of " + breakType + + "s during the performance test. Cannot continue the performance test."); + } + + public long getOperationsPerIteration() { + return fileContents.length(); + } + }; + } + + PerfTest.Function TestICUSentences() { + return createTestICU(iSentenceIter, iSentences, "sentence"); + } + + PerfTest.Function TestICUWords() { + return createTestICU(iWordIter, iWords, "word"); + } + + PerfTest.Function TestICULines() { + return createTestICU(iLineIter, iLines, "line"); + } + + PerfTest.Function TestICUCharacters() { + return createTestICU(iCharacterIter, iCharacters, "character"); + } + + PerfTest.Function TestJavaSentences() { + return createTestJava(jSentenceIter, jSentences, "sentence"); + } + + PerfTest.Function TestJavaWords() { + return createTestJava(jWordIter, jWords, "word"); + } + + PerfTest.Function TestJavaLines() { + return createTestJava(jLineIter, jLines, "line"); + } + + PerfTest.Function TestJavaCharacters() { + return createTestJava(jCharacterIter, jCharacters, "character"); + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/CollationPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/CollationPerformanceTest.java new file mode 100644 index 000000000..d8dfceed2 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/CollationPerformanceTest.java @@ -0,0 +1,1273 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/** +******************************************************************************* +* Copyright (C) 2002-2007, International Business Machines Corporation and * +* others. All Rights Reserved. * +******************************************************************************* +*/ + +package com.ibm.icu.dev.test.perf; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Comparator; + +import com.ibm.icu.impl.LocaleUtility; +import com.ibm.icu.text.CollationElementIterator; +import com.ibm.icu.text.CollationKey; +import com.ibm.icu.text.Normalizer; +import com.ibm.icu.text.NumberFormat; +import com.ibm.icu.text.RuleBasedCollator; + +public class CollationPerformanceTest { + static final String usageString = + "usage: collperf options...\n" + + "-help Display this message.\n" + + "-file file_name utf-16 format file of names.\n" + + "-locale name ICU locale to use. Default is en_US\n" + + "-rules file_name Collation rules file (overrides locale)\n" + //+ "-langid 0x1234 Windows Language ID number. Default to value for -locale option\n" + //+ " see http://msdn.microsoft.com/library/psdk/winbase/nls_8xo3.htm\n" + //+ "-win Run test using Windows native services. (ICU is default)\n" + //+ "-unix Run test using Unix strxfrm, strcoll services.\n" + //+ "-uselen Use API with string lengths. Default is null-terminated strings\n" + + "-usekeys Run tests using sortkeys rather than strcoll\n" + + "-strcmp Run tests using u_strcmp rather than strcoll\n" + + "-strcmpCPO Run tests using u_strcmpCodePointOrder rather than strcoll\n" + + "-loop nnnn Loopcount for test. Adjust for reasonable total running time.\n" + + "-iloop n Inner Loop Count. Default = 1. Number of calls to function\n" + + " under test at each call point. For measuring test overhead.\n" + + "-terse Terse numbers-only output. Intended for use by scripts.\n" + + "-french French accent ordering\n" + + "-frenchoff No French accent ordering (for use with French locales.)\n" + + "-norm Normalizing mode on\n" + + "-shifted Shifted mode\n" + + "-lower Lower case first\n" + + "-upper Upper case first\n" + + "-case Enable separate case level\n" + + "-level n Sort level, 1 to 5, for Primary, Secndary, Tertiary, Quaternary, Identical\n" + + "-keyhist Produce a table sort key size vs. string length\n" + + "-binsearch Binary Search timing test\n" + + "-keygen Sort Key Generation timing test\n" + + "-qsort Quicksort timing test\n" + + "-iter Iteration Performance Test\n" + + "-dump Display strings, sort keys and CEs.\n" + + "-java Run test using java.text.Collator.\n"; + + //enum {FLAG, NUM, STRING} type; + static StringBuffer temp_opt_fName = new StringBuffer(""); + static StringBuffer temp_opt_locale = new StringBuffer("en_US"); + //static StringBuffer temp_opt_langid = new StringBuffer("0"); // Defaults to value corresponding to opt_locale. + static StringBuffer temp_opt_rules = new StringBuffer(""); + static StringBuffer temp_opt_help = new StringBuffer(""); + static StringBuffer temp_opt_loopCount = new StringBuffer("1"); + static StringBuffer temp_opt_iLoopCount = new StringBuffer("1"); + static StringBuffer temp_opt_terse = new StringBuffer("false"); + static StringBuffer temp_opt_qsort = new StringBuffer(""); + static StringBuffer temp_opt_binsearch = new StringBuffer(""); + static StringBuffer temp_opt_icu = new StringBuffer("true"); + //static StringBuffer opt_win = new StringBuffer(""); // Run with Windows native functions. + //static StringBuffer opt_unix = new StringBuffer(""); // Run with UNIX strcoll, strxfrm functions. + //static StringBuffer opt_uselen = new StringBuffer(""); + static StringBuffer temp_opt_usekeys = new StringBuffer(""); + static StringBuffer temp_opt_strcmp = new StringBuffer(""); + static StringBuffer temp_opt_strcmpCPO = new StringBuffer(""); + static StringBuffer temp_opt_norm = new StringBuffer(""); + static StringBuffer temp_opt_keygen = new StringBuffer(""); + static StringBuffer temp_opt_french = new StringBuffer(""); + static StringBuffer temp_opt_frenchoff = new StringBuffer(""); + static StringBuffer temp_opt_shifted = new StringBuffer(""); + static StringBuffer temp_opt_lower = new StringBuffer(""); + static StringBuffer temp_opt_upper = new StringBuffer(""); + static StringBuffer temp_opt_case = new StringBuffer(""); + static StringBuffer temp_opt_level = new StringBuffer("0"); + static StringBuffer temp_opt_keyhist = new StringBuffer(""); + static StringBuffer temp_opt_itertest = new StringBuffer(""); + static StringBuffer temp_opt_dump = new StringBuffer(""); + static StringBuffer temp_opt_java = new StringBuffer(""); + + + static String opt_fName = ""; + static String opt_locale = "en_US"; + //static int opt_langid = 0; // Defaults to value corresponding to opt_locale. + static String opt_rules = ""; + static boolean opt_help = false; + static int opt_loopCount = 1; + static int opt_iLoopCount = 1; + static boolean opt_terse = false; + static boolean opt_qsort = false; + static boolean opt_binsearch = false; + static boolean opt_icu = true; + //static boolean opt_win = false; // Run with Windows native functions. + //static boolean opt_unix = false; // Run with UNIX strcoll, strxfrm functions. + //static boolean opt_uselen = false; + static boolean opt_usekeys = false; + static boolean opt_strcmp = false; + static boolean opt_strcmpCPO = false; + static boolean opt_norm = false; + static boolean opt_keygen = false; + static boolean opt_french = false; + static boolean opt_frenchoff = false; + static boolean opt_shifted = false; + static boolean opt_lower = false; + static boolean opt_upper = false; + static boolean opt_case = false; + static int opt_level = 0; + static boolean opt_keyhist = false; + static boolean opt_itertest = false; + static boolean opt_dump = false; + static boolean opt_java = false; + + static OptionSpec[] options = { + new OptionSpec("-file", 2, temp_opt_fName), + new OptionSpec("-locale", 2, temp_opt_locale), + //new OptionSpec("-langid", 1, temp_opt_langid), + new OptionSpec("-rules", 2, temp_opt_rules), + new OptionSpec("-qsort", 0, temp_opt_qsort), + new OptionSpec("-binsearch", 0, temp_opt_binsearch), + new OptionSpec("-iter", 0, temp_opt_itertest), + //new OptionSpec("-win", 0, temp_opt_win), + //new OptionSpec("-unix", 0, temp_opt_unix), + //new OptionSpec("-uselen", 0, temp_opt_uselen), + new OptionSpec("-usekeys", 0, temp_opt_usekeys), + new OptionSpec("-strcmp", 0, temp_opt_strcmp), + new OptionSpec("-strcmpCPO", 0, temp_opt_strcmpCPO), + new OptionSpec("-norm", 0, temp_opt_norm), + new OptionSpec("-french", 0, temp_opt_french), + new OptionSpec("-frenchoff", 0, temp_opt_frenchoff), + new OptionSpec("-shifted", 0, temp_opt_shifted), + new OptionSpec("-lower", 0, temp_opt_lower), + new OptionSpec("-upper", 0, temp_opt_upper), + new OptionSpec("-case", 0, temp_opt_case), + new OptionSpec("-level", 1, temp_opt_level), + new OptionSpec("-keyhist", 0, temp_opt_keyhist), + new OptionSpec("-keygen", 0, temp_opt_keygen), + new OptionSpec("-loop", 1, temp_opt_loopCount), + new OptionSpec("-iloop", 1, temp_opt_iLoopCount), + new OptionSpec("-terse", 0, temp_opt_terse), + new OptionSpec("-dump", 0, temp_opt_dump), + new OptionSpec("-help", 0, temp_opt_help), + new OptionSpec("-?", 0, temp_opt_help), + new OptionSpec("-java", 0, temp_opt_java), + }; + + static java.text.Collator javaCol = null; + static com.ibm.icu.text.Collator icuCol = null; + static NumberFormat nf = null; + static NumberFormat percent = null; + ArrayList list = null; + String[] tests = null; + int globalCount = 0; + + public static void main(String[] args) { + CollationPerformanceTest collPerf = new CollationPerformanceTest(); + if ( !CollationPerformanceTest.processOptions(args) || opt_help || opt_fName.length()==0) { + System.out.println(usageString); + System.exit(1); + } + + nf = NumberFormat.getInstance(); + nf.setMaximumFractionDigits(2); + percent = NumberFormat.getPercentInstance(); + + collPerf.setOptions(); + collPerf.readDataLines(); + + if (opt_dump) { + collPerf.doDump(); + } + + if (opt_qsort) { + collPerf.doQSort(); + } + + if (opt_binsearch) { + collPerf.doBinarySearch(); + } + + if (opt_keygen) { + collPerf.doKeyGen(); + } + + if (opt_keyhist) { + collPerf.doKeyHist(); + } + + if (opt_itertest) { + collPerf.doIterTest(); + } + + } + + //Dump file lines, CEs, Sort Keys if requested + void doDump() { + for(int i = 0; i < list.size(); i++) { + //print the line + String line = com.ibm.icu.impl.Utility.escape((String)list.get(i)); + System.out.println(line); + + System.out.print(" CEs: "); + CollationElementIterator CEiter = ((com.ibm.icu.text.RuleBasedCollator)icuCol).getCollationElementIterator(line); + int ce; + int j = 0; + for(;;) { + ce = CEiter.next(); + if (ce == CollationElementIterator.NULLORDER) { + break; + } + //System.out.print(); + String outStr = Integer.toHexString(ce); + for (int len = 0; len < 8 - outStr.length(); len++) { + outStr ='0' + outStr; + } + System.out.print(outStr + " "); + if(++j >8) { + System.out.print("\n "); + j = 0; + } + } + + System.out.print("\n ICU Sort Key: "); + CollationKey ck = ((com.ibm.icu.text.RuleBasedCollator)icuCol).getCollationKey(line); + byte[] cks = ck.toByteArray(); + j = 0; + for(int k = 0; k < cks.length; k++) { + String outStr = Integer.toHexString(cks[k]); + switch (outStr.length()) { + case 1: outStr = '0' + outStr; + break; + case 8: outStr = outStr.substring(6); + break; + } + System.out.print(outStr); + System.out.print(" "); + j++; + if(j > 0 && j % 20 == 0) { + System.out.print("\n "); + } + } + System.out.println("\n"); + } + } + + /**--------------------------------------------------------------------------------------- + * + * doQSort() The quick sort timing test. + * + *--------------------------------------------------------------------------------------- + */ + void doQSort() { + callGC(); + //String[] sortTests = (String[]) tests.clone(); + //Adjust loop count to compensate for file size. QSort should be nlog(n) + double dLoopCount = opt_loopCount * 3000 / ((Math.log(tests.length) / Math.log(10)* tests.length)); + + if(opt_usekeys) { + dLoopCount *= 5; + } + + int adj_loopCount = (int)dLoopCount; + if(adj_loopCount < 1) { + adj_loopCount = 1; + } + + globalCount = 0; + long startTime = 0; + long endTime = 0; + if (opt_icu && opt_usekeys) { + startTime = System.currentTimeMillis(); + qSortImpl_icu_usekeys(tests, 0, tests.length -1, icuCol); + endTime = System.currentTimeMillis(); + } + if (opt_icu && !opt_usekeys){ + startTime = System.currentTimeMillis(); + qSortImpl_nokeys(tests, 0, tests.length -1, icuCol); + endTime = System.currentTimeMillis(); + } + if (opt_java && opt_usekeys) { + startTime = System.currentTimeMillis(); + qSortImpl_java_usekeys(tests, 0, tests.length -1, javaCol); + endTime = System.currentTimeMillis(); + } + if (opt_java && !opt_usekeys){ + startTime = System.currentTimeMillis(); + qSortImpl_nokeys(tests, 0, tests.length -1, javaCol); + endTime = System.currentTimeMillis(); + } + long elapsedTime = endTime - startTime; + int ns = (int)(1000000 * elapsedTime / (globalCount + 0.0)); + if (!opt_terse) { + System.out.println("qsort: total # of string compares = " + globalCount); + System.out.println("qsort: time per compare = " + ns); + } else { + System.out.println(ns); + } + } + + /**--------------------------------------------------------------------------------------- + * + * doBinarySearch() Binary Search timing test. Each name from the list + * is looked up in the full sorted list of names. + * + *--------------------------------------------------------------------------------------- + */ + void doBinarySearch() { + callGC(); + int gCount = 0; + int loops = 0; + double dLoopCount = opt_loopCount * 3000 / (Math.log(tests.length) / Math.log(10)* tests.length); + long startTime = 0; + long elapsedTime = 0; + + if(opt_usekeys) { + dLoopCount *= 5; + } + int adj_loopCount = (int)dLoopCount; + if(adj_loopCount < 1) { + adj_loopCount = 1; + } + + //int opt2 = 0; + + for(;;) { //not really a loop, just allows "break" to work, to simplify + //inadvertently running more than one test through here + if(opt_strcmp) { + int r = 0; + startTime = System.currentTimeMillis(); + for(loops = 0; loops < adj_loopCount; loops++) { + for (int j = 0; j < tests.length; j++) { + int hi = tests.length-1; + int lo = 0; + int guess = -1; + for(;;) { + int newGuess = (hi + lo) / 2; + if(newGuess == guess){ + break; + } + guess = newGuess; + r = tests[j].compareTo(tests[guess]); + gCount++; + if(r == 0) { + break; + } + if (r < 0) { + hi = guess; + } else { + lo = guess; + } + } + } + } + elapsedTime = System.currentTimeMillis() - startTime; + break; + } + + if (opt_strcmpCPO) { + int r = 0; + startTime = System.currentTimeMillis(); + for(loops = 0; loops < adj_loopCount; loops++) { + for (int j = 0; j < tests.length; j++) { + int hi = tests.length-1; + int lo = 0; + int guess = -1; + for(;;) { + int newGuess = (hi + lo) / 2; + if(newGuess == guess){ + break; + } + guess = newGuess; + r = com.ibm.icu.text.Normalizer.compare(tests[j], tests[guess], Normalizer.COMPARE_CODE_POINT_ORDER); + gCount++; + if(r == 0) { + break; + } + if (r < 0) { + hi = guess; + } else { + lo = guess; + } + } + } + } + elapsedTime = System.currentTimeMillis() - startTime; + break; + } + + if (opt_icu) { + + int r = 0; + startTime = System.currentTimeMillis(); + for (loops = 0; loops < adj_loopCount; loops++) { + for (int j = 0; j < tests.length; j++) { + int hi = tests.length - 1; + int lo = 0; + int guess = -1; + for (;;) { + int newGuess = (hi + lo) / 2; + if (newGuess == guess) { + break; + } + guess = newGuess; + if (opt_usekeys) { + com.ibm.icu.text.CollationKey sortKey1 = icuCol.getCollationKey(tests[j]); + com.ibm.icu.text.CollationKey sortKey2 = icuCol.getCollationKey(tests[guess]); + r = sortKey1.compareTo(sortKey2); + gCount ++; + } else { + r = icuCol.compare(tests[j], tests[guess]); + gCount++; + } + if (r == 0) { + break; + } + if (r < 0) { + hi = guess; + } else { + lo = guess; + } + } + } + } + elapsedTime = System.currentTimeMillis() - startTime; + break; + } + if (opt_java) { + + int r = 0; + startTime = System.currentTimeMillis(); + for (loops = 0; loops < adj_loopCount; loops++) { + for (int j = 0; j < tests.length; j++) { + int hi = tests.length - 1; + int lo = 0; + int guess = -1; + for (;;) { + int newGuess = (hi + lo) / 2; + if (newGuess == guess) { + break; + } + guess = newGuess; + if (opt_usekeys) { + java.text.CollationKey sortKey1 = javaCol.getCollationKey(tests[j]); + java.text.CollationKey sortKey2 = javaCol.getCollationKey(tests[guess]); + r = sortKey1.compareTo(sortKey2); + gCount ++; + } else { + r = javaCol.compare(tests[j], tests[guess]); + gCount++; + } + if (r == 0) { + break; + } + if (r < 0) { + hi = guess; + } else { + lo = guess; + } + } + } + } + elapsedTime = System.currentTimeMillis() - startTime; + break; + } + break; + } + int ns = (int)((float)(1000000) * (float)elapsedTime / (float)gCount); + if (!opt_terse) { + System.out.println("binary search: total # of string compares = " + gCount); + System.out.println("binary search: compares per loop = " + gCount / loops); + System.out.println("binary search: time per compare = " + ns); + } else { + System.out.println(ns); + } + } + + /**--------------------------------------------------------------------------------------- + * + * doKeyGen() Key Generation Timing Test + * + *--------------------------------------------------------------------------------------- + */ + void doKeyGen() { + callGC(); + + // Adjust loop count to compensate for file size. Should be order n + double dLoopCount = opt_loopCount * (1000.0 / (double)list.size()); + int adj_loopCount = (int)dLoopCount; + if (adj_loopCount < 1) adj_loopCount = 1; + + long startTime = 0; + long totalKeyLen = 0; + long totalChars = 0; + if (opt_java) { + startTime = System.currentTimeMillis(); + for (int loops=0; loops<adj_loopCount; loops++) { + for (int line=0; line < tests.length; line++) { + for (int iLoop=0; iLoop < opt_iLoopCount; iLoop++) { + totalChars += tests[line].length(); + byte[] sortKey = javaCol.getCollationKey(tests[line]).toByteArray(); + totalKeyLen += sortKey.length; + } + } + } + } else { + startTime = System.currentTimeMillis(); + for (int loops=0; loops<adj_loopCount; loops++) { + for (int line=0; line < tests.length; line++) { + for (int iLoop=0; iLoop < opt_iLoopCount; iLoop++) { + totalChars += tests[line].length(); + byte[] sortKey = icuCol.getCollationKey(tests[line]).toByteArray(); + totalKeyLen += sortKey.length; + } + } + } + } + + long elapsedTime = System.currentTimeMillis() - startTime; + long ns = (long)(1000000 * elapsedTime / (adj_loopCount * tests.length + 0.0)); + if (!opt_terse) { + System.out.println("Sort Key Generation: total # of keys =" + adj_loopCount * tests.length); + System.out.println("Sort Key Generation: time per key = " + ns + " ns"); + System.out.println("Key Length / character = " + nf.format(totalKeyLen / (totalChars + 0.0))); + } + else { + System.out.print(ns + ", "); + System.out.println(nf.format(totalKeyLen / (totalChars + 0.0)) + ", "); + } + } + + /**--------------------------------------------------------------------------------------- + * + * doKeyHist() Output a table of data for average sort key size vs. string length. + * + *--------------------------------------------------------------------------------------- + */ + void doKeyHist() { + callGC(); + int maxLen = 0; + + // Find the maximum string length + for (int i = 0; i < tests.length; i++) { + if (tests[i].length() > maxLen) maxLen = tests[i].length(); + } + + int[] accumulatedLen = new int[maxLen + 1]; + int[] numKeysOfSize = new int[maxLen + 1]; + + // Fill the arrays... + for (int i = 0; i < tests.length; i++) { + int len = tests[i].length(); + accumulatedLen[len] += icuCol.getCollationKey(tests[i]).toByteArray().length; + numKeysOfSize[len] += 1; + } + + // And write out averages + System.out.println("String Length, Avg Key Length, Avg Key Len per char"); + for (int i = 1; i <= maxLen; i++) { + if (numKeysOfSize[i] > 0) { + System.out.println(i + ", " + nf.format(accumulatedLen[i] / (numKeysOfSize[i]+ 0.0)) + ", " + + nf.format(accumulatedLen[i] / (numKeysOfSize[i] * i + 0.0))); + } + } + + } + + void doForwardIterTest() { + callGC(); + System.out.print("\n\nPerforming forward iteration performance test with "); + System.out.println("performance test on strings from file -----------"); + + CollationElementIterator iter = ((RuleBasedCollator)icuCol).getCollationElementIterator(""); + + int gCount = 0; + int count = 0; + long startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int linecount = 0; + while (linecount < tests.length) { + String str = tests[linecount]; + iter.setText(str); + while (iter.next() != CollationElementIterator.NULLORDER) { + gCount++; + } + linecount ++; + } + count ++; + } + + long elapsedTime = System.currentTimeMillis() - startTime; + System.out.println("elapsedTime " + elapsedTime + " ms"); + + // empty loop recalculation + count = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int linecount = 0; + while (linecount < tests.length) { + String str = tests[linecount]; + iter.setText(str); + linecount ++; + } + count ++; + } + elapsedTime -= (System.currentTimeMillis() - startTime); + System.out.println("elapsedTime " + elapsedTime + " ms"); + + int ns = (int)(1000000 * elapsedTime / (gCount + 0.0)); + System.out.println("Total number of strings compared " + tests.length + + "in " + opt_loopCount + " loops"); + System.out.println("Average time per CollationElementIterator.next() nano seconds " + ns); + System.out.println("performance test on skipped-5 concatenated strings from file -----------"); + + String totalStr = ""; + int strlen = 0; + // appending all the strings + int linecount = 0; + while (linecount < tests.length) { + totalStr += tests[linecount]; + strlen += tests[linecount].length(); + linecount ++; + } + System.out.println("Total size of strings " + strlen); + + gCount = 0; + count = 0; + iter = ((RuleBasedCollator)icuCol).getCollationElementIterator(totalStr); + strlen -= 5; // any left over characters are not iterated, + // this is to ensure the backwards and forwards iterators + // gets the same position + int strindex = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int count5 = 5; + strindex = 0; + iter.setOffset(strindex); + while (true) { + if (iter.next() == CollationElementIterator.NULLORDER) { + break; + } + gCount++; + count5 --; + if (count5 == 0) { + strindex += 10; + if (strindex > strlen) { + break; + } + iter.setOffset(strindex); + count5 = 5; + } + } + count ++; + } + + elapsedTime = System.currentTimeMillis() - startTime; + System.out.println("elapsedTime " + elapsedTime); + + // empty loop recalculation + int tempgCount = 0; + count = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int count5 = 5; + strindex = 0; + iter.setOffset(strindex); + while (true) { + tempgCount ++; + count5 --; + if (count5 == 0) { + strindex += 10; + if (strindex > strlen) { + break; + } + iter.setOffset(strindex); + count5 = 5; + } + } + count ++; + } + elapsedTime -= (System.currentTimeMillis() - startTime); + System.out.println("elapsedTime " + elapsedTime); + + System.out.println("gCount " + gCount); + ns = (int)(1000000 * elapsedTime / (gCount + 0.0)); + System.out.println("Average time per CollationElementIterator.next() nano seconds " + ns); + } + + void doBackwardIterTest() { + System.out.print("\n\nPerforming backward iteration performance test with "); + System.out.println("performance test on strings from file -----------\n"); + + CollationElementIterator iter = ((RuleBasedCollator)icuCol).getCollationElementIterator(""); + + int gCount = 0; + int count = 0; + long startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int linecount = 0; + while (linecount < tests.length) { + String str = tests[linecount]; + iter.setText(str); + while (iter.previous() != CollationElementIterator.NULLORDER) { + gCount++; + } + linecount ++; + } + count ++; + } + long elapsedTime = System.currentTimeMillis() - startTime; + System.out.println("elapsedTime " + elapsedTime + " ms"); + + // empty loop recalculation + count = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int linecount = 0; + while (linecount < tests.length) { + String str = tests[linecount]; + iter.setText(str); + linecount ++; + } + count ++; + } + elapsedTime -= (System.currentTimeMillis() - startTime); + System.out.println("elapsedTime " + elapsedTime + " ms"); + + int ns = (int)(1000000 * elapsedTime / (gCount + 0.0)); + System.out.println("Total number of strings compared " + tests.length + + "in " + opt_loopCount + " loops"); + System.out.println("Average time per CollationElementIterator.previous() nano seconds " + ns); + System.out.println("performance test on skipped-5 concatenated strings from file -----------"); + + String totalStr = ""; + int strlen = 0; + // appending all the strings + int linecount = 0; + while (linecount < tests.length) { + totalStr += tests[linecount]; + strlen += tests[linecount].length(); + linecount ++; + } + System.out.println("Total size of strings " + strlen); + + gCount = 0; + count = 0; + + iter = ((RuleBasedCollator)icuCol).getCollationElementIterator(totalStr); + int strindex = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int count5 = 5; + strindex = 5; + iter.setOffset(strindex); + while (true) { + if (iter.previous() == CollationElementIterator.NULLORDER) { + break; + } + gCount ++; + count5 --; + if (count5 == 0) { + strindex += 10; + if (strindex > strlen) { + break; + } + iter.setOffset(strindex); + count5 = 5; + } + } + count ++; + } + + elapsedTime = System.currentTimeMillis() - startTime; + System.out.println("elapsedTime " + elapsedTime); + + // empty loop recalculation + count = 0; + int tempgCount = 0; + startTime = System.currentTimeMillis(); + while (count < opt_loopCount) { + int count5 = 5; + strindex = 5; + iter.setOffset(strindex); + while (true) { + tempgCount ++; + count5 --; + if (count5 == 0) { + strindex += 10; + if (strindex > strlen) { + break; + } + iter.setOffset(strindex); + count5 = 5; + } + } + count ++; + } + elapsedTime -= (System.currentTimeMillis() - startTime); + System.out.println("elapsedTime " + elapsedTime); + + System.out.println("gCount " + gCount); + ns = (int)(1000000 * elapsedTime / (gCount + 0.0)); + System.out.println("Average time per CollationElementIterator.previous() nano seconds " + ns); + } + + + /**--------------------------------------------------------------------------------------- + * + * doIterTest() Iteration test + * + *--------------------------------------------------------------------------------------- + */ + void doIterTest() { + doForwardIterTest(); + doBackwardIterTest(); + } + + void setOptions() { + + if (opt_java) { + opt_icu = false; + } + + if (opt_rules.length() != 0) { + try { + icuCol = new com.ibm.icu.text.RuleBasedCollator(getCollationRules(opt_rules)); + } catch (Exception e) { + System.out.println("Cannot open rules:" + e.getMessage()); + System.exit(1); + } + } else { + icuCol = com.ibm.icu.text.Collator.getInstance( + LocaleUtility.getLocaleFromName(opt_locale)); + } + + javaCol = java.text.Collator.getInstance( + LocaleUtility.getLocaleFromName(opt_locale)); + + if (opt_norm) { + javaCol.setDecomposition(java.text.Collator.CANONICAL_DECOMPOSITION); + icuCol.setDecomposition(com.ibm.icu.text.Collator.CANONICAL_DECOMPOSITION); + } + + if (opt_french && opt_frenchoff) { + System.err.println("Error: specified both -french and -frenchoff options."); + } + + if (opt_french) { + ((com.ibm.icu.text.RuleBasedCollator)icuCol).setFrenchCollation(true); + } + if (opt_frenchoff) { + ((com.ibm.icu.text.RuleBasedCollator)icuCol).setFrenchCollation(false); + } + + if (opt_lower) { + ((com.ibm.icu.text.RuleBasedCollator)icuCol).setLowerCaseFirst(true); + } + + if (opt_upper) { + ((com.ibm.icu.text.RuleBasedCollator)icuCol).setUpperCaseFirst(true); + } + + if (opt_shifted) { + ((com.ibm.icu.text.RuleBasedCollator)icuCol).setAlternateHandlingShifted(true); + } + + if (opt_level != 0) { + switch (opt_level) { + case 1 : + javaCol.setStrength(java.text.Collator.PRIMARY); + icuCol.setStrength(com.ibm.icu.text.Collator.PRIMARY); + break; + case 2 : + javaCol.setStrength(java.text.Collator.SECONDARY); + icuCol.setStrength(com.ibm.icu.text.Collator.SECONDARY); + break; + case 3 : + javaCol.setStrength(java.text.Collator.TERTIARY); + icuCol.setStrength(com.ibm.icu.text.Collator.TERTIARY); + break; + case 4 : + icuCol.setStrength(com.ibm.icu.text.Collator.QUATERNARY); + break; + case 5 : + javaCol.setStrength(java.text.Collator.IDENTICAL); + icuCol.setStrength(com.ibm.icu.text.Collator.IDENTICAL); + break; + default: + System.err.println("-level param must be between 1 and 5\n"); + System.exit(1); + } + } + // load classes at least once before starting + javaCol.compare("a", "b"); + icuCol.compare("a", "b"); + } + + static boolean processOptions(String[] args) { + int argNum; + for (argNum =0; argNum < args.length; argNum++) { + for (int i = 0; i < options.length; i++) { + if (args[argNum].equalsIgnoreCase(options[i].name)) { + switch (options[i].type) { + case 0: + options[i].value.delete(0, options[i].value.capacity()).append("true"); + break; + case 1: + argNum++; + if ((argNum >= args.length) || (args[argNum].charAt(0)=='-')) { + System.err.println("value expected for"+ options[i].name +"option.\n"); + return false; + } + try { + /* int value =*/ Integer.parseInt(args[argNum]); + options[i].value.delete(0, options[i].value.capacity()).append(args[argNum]); + } catch (NumberFormatException e) { + System.err.println("Expected: a number value"); + return false; + } + break; + case 2: + argNum++; + if ((argNum >= args.length) || (args[argNum].charAt(0)=='-')) { + System.err.println("value expected for"+ options[i].name +"option.\n"); + return false; + } + options[i].value.delete(0, options[i].value.capacity()).append(args[argNum]); + break; + default: + System.err.println("Option type error: {FLAG=0, NUM=1, STRING=2}"); + return false; + } + } + } + } + + opt_fName = temp_opt_fName.toString(); + opt_locale = temp_opt_locale.toString(); + opt_rules = temp_opt_rules.toString(); + if (temp_opt_help.toString().equalsIgnoreCase("true")) { + opt_help = true; + } + opt_loopCount = Integer.parseInt(temp_opt_loopCount.toString()); + opt_iLoopCount = Integer.parseInt(temp_opt_iLoopCount.toString()); + if (temp_opt_terse.toString().equalsIgnoreCase("true")) { + opt_terse = true; + } + if (temp_opt_qsort.toString().equalsIgnoreCase("true")) { + opt_qsort = true; + } + if (temp_opt_binsearch.toString().equalsIgnoreCase("true")) { + opt_binsearch = true; + } + if (temp_opt_icu.toString().equalsIgnoreCase("true")) { + opt_icu = true; + } + if (temp_opt_usekeys.toString().equalsIgnoreCase("true")) { + opt_usekeys = true; + } + if (temp_opt_strcmp.toString().equalsIgnoreCase("true")) { + opt_strcmp = true; + } + if (temp_opt_strcmpCPO.toString().equalsIgnoreCase("true")) { + opt_strcmpCPO = true; + } + if (temp_opt_keygen.toString().equalsIgnoreCase("true")) { + opt_keygen = true; + } + if (temp_opt_norm.toString().equalsIgnoreCase("true")) { + opt_norm = true; + } + if (temp_opt_french.toString().equalsIgnoreCase("true")) { + opt_french = true; + } + if (temp_opt_frenchoff.toString().equalsIgnoreCase("true")) { + opt_frenchoff = true; + } + if (temp_opt_shifted.toString().equalsIgnoreCase("true")) { + opt_shifted = true; + } + if (temp_opt_lower.toString().equalsIgnoreCase("true")) { + opt_lower = true; + } + if (temp_opt_upper.toString().equalsIgnoreCase("true")) { + opt_upper = true; + } + if (temp_opt_case.toString().equalsIgnoreCase("true")) { + opt_case = true; + } + opt_level = Integer.parseInt(temp_opt_level.toString()); + if (temp_opt_keyhist.toString().equalsIgnoreCase("true")) { + opt_keyhist = true; + } + if (temp_opt_itertest.toString().equalsIgnoreCase("true")) { + opt_itertest = true; + } + if (temp_opt_dump.toString().equalsIgnoreCase("true")) { + opt_dump = true; + } + if (temp_opt_java.toString().equalsIgnoreCase("true")) { + opt_java = true; + } + + return true; + } + + /** + * Invoke the runtime's garbage collection procedure repeatedly + * until the amount of free memory stabilizes to within 10%. + */ + private void callGC() { + // From "Java Platform Performance". This is the procedure + // recommended by Javasoft. + try { + System.gc(); + Thread.sleep(100); + System.runFinalization(); + Thread.sleep(100); + + System.gc(); + Thread.sleep(100); + System.runFinalization(); + Thread.sleep(100); + } catch (InterruptedException e) {} + } + + //private boolean needCRLF = false; + + public int DOTMASK = 0x7FF; + + void dot(int i) { + if ((i % DOTMASK) == 0) { + //needCRLF = true; + // I do not know why print the dot here + //System.out.print('.'); + } + } + + String readDataLine(BufferedReader br) throws Exception { + String originalLine = ""; + String line = ""; + + try { + line = originalLine = br.readLine(); + if (line == null) return null; + if (line.length() > 0 && line.charAt(0) == 0xFEFF) line = line.substring(1); + int commentPos = line.indexOf('#'); + if (commentPos >= 0) line = line.substring(0, commentPos); + line = line.trim(); + } catch (Exception e) { + throw new Exception("Line \"{0}\", \"{1}\"" + originalLine + " " + + line + " " + e.toString()); + } + return line; + } + + void readDataLines() { + // Read in the input file. + // File assumed to be utf-16. + // Lines go onto heap buffers. Global index array to line starts is created. + // Lines themselves are null terminated. + // + FileInputStream fis = null; + InputStreamReader isr = null; + BufferedReader br = null; + try { + fis = new FileInputStream(opt_fName); + isr = new InputStreamReader(fis, "UTF-8"); + br= new BufferedReader(isr, 32*1024); + } catch (Exception e) { + System.err.println("Error: File access exception: " + e.getMessage() + "!"); + System.exit(2); + } + + int counter = 0; + + list = new ArrayList(); + while (true) { + String line = null; + try { + line = readDataLine(br); + } catch (Exception e) { + System.err.println("Read File Error" + e.getMessage() + "!"); + System.exit(1); + } + + if (line == null) break; + if (line.length() == 0) continue; + dot(counter++); + list.add(line); + } + if (!opt_terse) { + System.out.println("Read " + counter + " lines in file"); + } + + int size = list.size(); + tests = new String [size]; + + for (int i = 0; i < size; ++i) { + tests[i] = (String) list.get(i); + } + } + + /** + * Get the Collator Rules + * The Rule File format: + * 1. leading and trailing whitespaces will be omitted + * 2. lines with the leading character '#' will be treated as comments + * 3. File encoding is ISO-8859-1 + */ + String getCollationRules(String ruleFileName) { + FileInputStream fis = null; + InputStreamReader isr = null; + BufferedReader br = null; + try { + fis = new FileInputStream(opt_rules); + isr = new InputStreamReader(fis,"ISO-8859-1"); + br= new BufferedReader(isr); + } catch (Exception e) { + System.err.println("Error: File access exception: " + e.getMessage() + "!"); + System.exit(2); + } + String rules = ""; + String line = ""; + while (true) { + try { + line = br.readLine(); + } catch (IOException e) { + System.err.println("Read File Error" + e.getMessage() + "!"); + System.exit(1); + } + if (line == null) { + break; + } + int commentPos = line.indexOf('#'); + if (commentPos >= 0) line = line.substring(0, commentPos); + line = line.trim(); + rules = rules + line; + } + return rules; + } + + //Implementing qsort + void qSortImpl_java_usekeys(String src[], int fromIndex, int toIndex, java.text.Collator c) { + int low = fromIndex; + int high = toIndex; + String middle = ""; + if (high > low) { + middle = src[ (low + high) / 2 ]; + while(low <= high) { + while((low < toIndex) && (compare(c.getCollationKey(src[low]), c.getCollationKey(middle)) < 0)) { + ++low; + } + while((high > fromIndex) && (compare(c.getCollationKey(src[high]), c.getCollationKey(middle)) > 0)) { + --high; + } + if(low <= high) { + String swap = src[low]; + src[low] = src[high]; + src[high] = swap; + ++low; + --high; + } + } + if(fromIndex < high) { + qSortImpl_java_usekeys(src, fromIndex, high, c); + } + + if(low < toIndex) { + qSortImpl_java_usekeys(src, low, toIndex, c); + } + } + } + + void qSortImpl_icu_usekeys(String src[], int fromIndex, int toIndex, com.ibm.icu.text.Collator c) { + int low = fromIndex; + int high = toIndex; + String middle = ""; + if (high > low) { + middle = src[ (low + high) / 2 ]; + while(low <= high) { + while((low < toIndex) && (compare(c.getCollationKey(src[low]), c.getCollationKey(middle)) < 0)) { + ++low; + } + while((high > fromIndex) && (compare(c.getCollationKey(src[high]), c.getCollationKey(middle)) > 0)) { + --high; + } + if(low <= high) { + String swap = src[low]; + src[low] = src[high]; + src[high] = swap; + ++low; + --high; + } + } + if(fromIndex < high) { + qSortImpl_icu_usekeys(src, fromIndex, high, c); + } + + if(low < toIndex) { + qSortImpl_icu_usekeys(src, low, toIndex, c); + } + } + } + + void qSortImpl_nokeys(String src[], int fromIndex, int toIndex, Comparator c) { + int low = fromIndex; + int high = toIndex; + String middle = ""; + if (high > low) { + middle = src[ (low + high) / 2 ]; + while(low <= high) { + while((low < toIndex) && (compare(src[low], middle, c) < 0)) { + ++low; + } + while((high > fromIndex) && (compare(src[high], middle, c) > 0)) { + --high; + } + if(low <= high) { + String swap = src[low]; + src[low] = src[high]; + src[high] = swap; + ++low; + --high; + } + } + if(fromIndex < high) { + qSortImpl_nokeys(src, fromIndex, high, c); + } + + if(low < toIndex) { + qSortImpl_nokeys(src, low, toIndex, c); + } + } + } + + int compare(String source, String target, Comparator c) { + globalCount++; + return c.compare(source, target); + } + + int compare(java.text.CollationKey source, java.text.CollationKey target) { + globalCount++; + return source.compareTo(target); + } + + int compare(com.ibm.icu.text.CollationKey source, com.ibm.icu.text.CollationKey target) { + globalCount++; + return source.compareTo(target); + } + + //Class for command line option + static class OptionSpec { + String name; + int type; + StringBuffer value; + public OptionSpec(String name, int type, StringBuffer value) { + this.name = name; + this.type = type; + this.value = value; + } + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ConverterPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ConverterPerformanceTest.java new file mode 100644 index 000000000..dade682b6 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ConverterPerformanceTest.java @@ -0,0 +1,320 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + ******************************************************************************* + * Copyright (C) 2002-2008, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.dev.test.perf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; + +import com.ibm.icu.charset.CharsetProviderICU; + +/** + * @author ram + */ +public class ConverterPerformanceTest extends PerfTest { + public static void main(String[] args) throws Exception { + new ConverterPerformanceTest().run(args); + } + char[] unicodeBuffer = null; + byte[] encBuffer = null; + + protected void setup(String[] args) { + try{ + // read in the input file, being careful with a possible BOM + FileInputStream in = new FileInputStream(fileName); + BOMFreeReader reader = new BOMFreeReader(in, encoding); + unicodeBuffer = readToEOS(reader); + + // use java.nio to convert unicodeBuffer from char[] to byte[] + CharBuffer source = CharBuffer.wrap(unicodeBuffer, 0, unicodeBuffer.length); + CharsetEncoder encoder = Charset.forName(encoding).newEncoder(); + encoder.onMalformedInput(CodingErrorAction.REPORT); + encoder.onUnmappableCharacter(CodingErrorAction.REPORT); + ByteBuffer target = encoder.encode(source); + + // target.array() will probably return what we want, but lets take no chances + encBuffer = new byte[target.limit()]; + for (int i=0; i<encBuffer.length; i++) + encBuffer[i] = target.get(i); + + } catch(Exception ex){ + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + + // we created some heavy objects, so lets try to clean up a little before running the tests + gc(); + } + + PerfTest.Function TestFromUnicodeStream() { + return new PerfTest.Function() { + public void call() { + try{ + ByteArrayOutputStream out = new ByteArrayOutputStream(unicodeBuffer.length * 10); + OutputStreamWriter writer = new OutputStreamWriter(out, testName); + writer.write(unicodeBuffer, 0, unicodeBuffer.length); + writer.flush(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return unicodeBuffer.length; + } + }; + } + PerfTest.Function TestToUnicodeStream() { + return new PerfTest.Function() { + char[] dst = new char[encBuffer.length]; + public void call() { + try{ + ByteArrayInputStream is = new ByteArrayInputStream(encBuffer, 0, encBuffer.length); + InputStreamReader reader = new InputStreamReader(is, testName); + reader.read(dst, 0, dst.length); + reader.close(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return encBuffer.length; + } + }; + } +/* + PerfTest.Function TestByteToCharConverter() { // decoder charset.forname().newencoder().decode + try{ + return new PerfTest.Function() { + char[] dst = new char[encBuffer.length]; + int numOut =0; + ByteToCharConverter conv = ByteToCharConverter.getConverter(testEncoderName); + int num =0; + public void call() { + try{ + numOut= conv.convert(encBuffer, 0, encBuffer.length, dst, 0,dst.length); + conv.reset(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return encBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestCharToByteConverter() { // encoder charset.forname().newencoder().encode + try{ + return new PerfTest.Function() { + byte[] dst = new byte[encBuffer.length]; + int numOut =0; + CharToByteConverter conv = CharToByteConverter.getConverter(testEncoderName); + int num =0; + public void call() { + try{ + numOut= conv.convert(unicodeBuffer, 0,unicodeBuffer.length,dst,0, dst.length); + conv.reset(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return unicodeBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestByteToCharConverterICU() { // decoder charsetprovidericu.getdecoder + try{ + return new PerfTest.Function() { + char[] dst = new char[encBuffer.length]; + int numOut =0; + ByteToCharConverter conv = ByteToCharConverterICU.createConverter(testEncoderName); + int num =0; + public void call() { + try{ + numOut= conv.convert(encBuffer, 0, encBuffer.length, dst, 0,dst.length); + conv.reset(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return encBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestCharToByteConverterICU() { + try{ + return new PerfTest.Function() { + byte[] dst = new byte[encBuffer.length*2]; + int numOut =0; + CharToByteConverter conv = CharToByteConverterICU.createConverter(testEncoderName); + int num =0; + public void call() { + try{ + numOut= conv.convert(unicodeBuffer, 0,unicodeBuffer.length,dst,0, dst.length); + conv.reset(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return unicodeBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } +*/ + PerfTest.Function TestCharsetDecoder() { + try{ + return new PerfTest.Function() { + CharBuffer outBuf = CharBuffer.allocate(unicodeBuffer.length); + Charset myCharset = Charset.forName(testName); + ByteBuffer srcBuf = ByteBuffer.wrap(encBuffer,0,encBuffer.length); + CharsetDecoder decoder = myCharset.newDecoder(); + + public void call() { + try{ + decoder.decode(srcBuf,outBuf,false); + decoder.reset(); + srcBuf.rewind(); + outBuf.rewind(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return encBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestCharsetEncoder() { + try{ + return new PerfTest.Function() { + ByteBuffer outBuf = ByteBuffer.allocate(encBuffer.length); + Charset myCharset = Charset.forName(testName); + CharBuffer srcBuf = CharBuffer.wrap(unicodeBuffer,0,unicodeBuffer.length); + CharsetEncoder encoder = myCharset.newEncoder(); + + public void call() { + try{ + encoder.encode(srcBuf,outBuf,false); + encoder.reset(); + srcBuf.rewind(); + outBuf.rewind(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return unicodeBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestCharsetDecoderICU() { + try{ + return new PerfTest.Function() { + CharBuffer outBuf = CharBuffer.allocate(unicodeBuffer.length); + Charset myCharset = new CharsetProviderICU().charsetForName(testName); + ByteBuffer srcBuf = ByteBuffer.wrap(encBuffer,0,encBuffer.length); + CharsetDecoder decoder = myCharset.newDecoder(); + + public void call() { + try{ + decoder.decode(srcBuf,outBuf,false); + decoder.reset(); + srcBuf.rewind(); + outBuf.rewind(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return encBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + + PerfTest.Function TestCharsetEncoderICU() { + try{ + return new PerfTest.Function() { + ByteBuffer outBuf = ByteBuffer.allocate(encBuffer.length); + Charset myCharset = new CharsetProviderICU().charsetForName(testName); + CharBuffer srcBuf = CharBuffer.wrap(unicodeBuffer,0,unicodeBuffer.length); + CharsetEncoder encoder = myCharset.newEncoder(); + + public void call() { + try{ + encoder.encode(srcBuf,outBuf,false); + encoder.reset(); + srcBuf.rewind(); + outBuf.rewind(); + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + public long getOperationsPerIteration() { + return unicodeBuffer.length; + } + }; + }catch(Exception e){ + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DateFormatPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DateFormatPerformanceTest.java new file mode 100644 index 000000000..16dba7aa5 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DateFormatPerformanceTest.java @@ -0,0 +1,117 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + * ****************************************************************************** + * Copyright (C) 2007, International Business Machines Corporation and others. * + * All Rights Reserved. * + * ****************************************************************************** + */ +package com.ibm.icu.dev.test.perf; + +import java.text.ParseException; +import java.util.Date; +import java.util.Locale; + +/** + * @author ajmacher + */ +public class DateFormatPerformanceTest extends PerfTest { + private String pattern; + + private String dateString; + + private Date date; + + private com.ibm.icu.text.SimpleDateFormat[] icuDateFormat; + + private java.text.SimpleDateFormat[] jdkDateFormat; + + public static void main(String[] args) throws Exception { + new DateFormatPerformanceTest().run(args); + } + + protected void setup(String[] args) { + try { + if (args.length == 0 || args.length > 2) { + throw new UsageException(); + } + + pattern = args[0]; + + if (locale == null) + locale = Locale.getDefault(); + + icuDateFormat = new com.ibm.icu.text.SimpleDateFormat[threads]; + jdkDateFormat = new java.text.SimpleDateFormat[threads]; + for (int i = 0; i < threads; i++) { + icuDateFormat[i] = new com.ibm.icu.text.SimpleDateFormat(pattern, locale); + jdkDateFormat[i] = new java.text.SimpleDateFormat(pattern, locale); + } + + if (args.length == 2) { + dateString = args[1]; + date = icuDateFormat[0].parse(dateString); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + + } + + PerfTest.Function TestICUConstruction() { + return new PerfTest.Function() { + public void call() { + new com.ibm.icu.text.SimpleDateFormat(pattern, locale); + } + }; + } + + PerfTest.Function TestJDKConstruction() { + return new PerfTest.Function() { + public void call() { + new java.text.SimpleDateFormat(pattern, locale); + } + }; + } + + PerfTest.Function TestICUParse() { + return new PerfTest.Function() { + public void call(int id) { + try { + icuDateFormat[id].parse(dateString); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + }; + } + + PerfTest.Function TestJDKParse() { + return new PerfTest.Function() { + public void call(int id) { + try { + jdkDateFormat[id].parse(dateString); + } catch (ParseException ex) { + ex.printStackTrace(); + } + } + }; + } + + PerfTest.Function TestICUFormat() { + return new PerfTest.Function() { + public void call(int id) { + icuDateFormat[id].format(date); + } + }; + } + + PerfTest.Function TestJDKFormat() { + return new PerfTest.Function() { + public void call(int id) { + jdkDateFormat[id].format(date); + } + }; + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DecimalFormatPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DecimalFormatPerformanceTest.java new file mode 100644 index 000000000..d41b1289a --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DecimalFormatPerformanceTest.java @@ -0,0 +1,121 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + * ****************************************************************************** + * Copyright (C) 2007, International Business Machines Corporation and * others. + * All Rights Reserved. * + * ****************************************************************************** + */ +package com.ibm.icu.dev.test.perf; + +import java.text.ParseException; +import java.util.Locale; + +/** + * @author ajmacher + */ +public class DecimalFormatPerformanceTest extends PerfTest { + String pattern; + + String decimalAsString; + + Number decimalAsNumber; + + com.ibm.icu.text.DecimalFormat[] icuDecimalFormat; + + java.text.DecimalFormat[] javaDecimalFormat; + + public static void main(String[] args) throws Exception { + new DecimalFormatPerformanceTest().run(args); + } + + protected void setup(String[] args) { + try { + if (args.length == 0 || args.length > 2) { + throw new UsageException(); + } + + pattern = args[0]; + + if (locale == null) + locale = Locale.getDefault(); + + icuDecimalFormat = new com.ibm.icu.text.DecimalFormat[threads]; + javaDecimalFormat = new java.text.DecimalFormat[threads]; + for (int i = 0; i < threads; i++) { + icuDecimalFormat[i] = new com.ibm.icu.text.DecimalFormat(pattern, + new com.ibm.icu.text.DecimalFormatSymbols(locale)); + javaDecimalFormat[i] = new java.text.DecimalFormat(pattern, + new java.text.DecimalFormatSymbols(locale)); + } + + if (args.length == 2) { + decimalAsString = args[1]; + decimalAsNumber = icuDecimalFormat[0].parse(decimalAsString); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + + } + + PerfTest.Function TestICUConstruction() { + return new PerfTest.Function() { + public void call() { + new com.ibm.icu.text.DecimalFormat(pattern, + new com.ibm.icu.text.DecimalFormatSymbols(locale)); + } + }; + } + + PerfTest.Function TestJDKConstruction() { + return new PerfTest.Function() { + public void call() { + new java.text.DecimalFormat(pattern, new java.text.DecimalFormatSymbols(locale)); + } + }; + } + + PerfTest.Function TestICUParse() { + return new PerfTest.Function() { + public void call(int id) { + try { + icuDecimalFormat[id].parse(decimalAsString); + } catch (ParseException e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + }; + } + + PerfTest.Function TestJDKParse() { + return new PerfTest.Function() { + public void call(int id) { + try { + javaDecimalFormat[id].parse(decimalAsString); + } catch (ParseException e) { + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } + } + }; + } + + PerfTest.Function TestICUFormat() { + return new PerfTest.Function() { + public void call(int id) { + icuDecimalFormat[id].format(decimalAsNumber); + } + }; + } + + PerfTest.Function TestJDKFormat() { + return new PerfTest.Function() { + public void call(int id) { + javaDecimalFormat[id].format(decimalAsNumber); + } + }; + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/NormalizerPerformanceTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/NormalizerPerformanceTest.java new file mode 100644 index 000000000..9d083f997 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/NormalizerPerformanceTest.java @@ -0,0 +1,704 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (c) 2002-2009, International Business Machines * +* Corporation and others. All Rights Reserved. * +********************************************************************** +*/ +package com.ibm.icu.dev.test.perf; + +import com.ibm.icu.text.Normalizer; + +public class NormalizerPerformanceTest extends PerfTest { + + String[] NFDFileLines; + String[] NFCFileLines; + String[] fileLines; + + + public static void main(String[] args) throws Exception { + new NormalizerPerformanceTest().run(args); + } + + protected void setup(String[] args) { + fileLines = readLines(fileName, encoding, bulk_mode); + NFDFileLines = normalizeInput(fileLines, Normalizer.NFD); + NFCFileLines = normalizeInput(fileLines, Normalizer.NFC); + } + + // Test NFC Performance + PerfTest.Function TestICU_NFC_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.normalize(NFDFileLines[i], Normalizer.NFC); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_NFC_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.normalize(NFCFileLines[i], Normalizer.NFC); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_NFC_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.normalize(fileLines[i], Normalizer.NFC); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + // Test NFD Performance + PerfTest.Function TestICU_NFD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.normalize(NFDFileLines[i], Normalizer.NFD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_NFD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.normalize(NFCFileLines[i], Normalizer.NFD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_NFD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.normalize(fileLines[i], Normalizer.NFD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + // Test NFC Performance + PerfTest.Function TestJDK_NFC_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) + normalizerTest(NFDFileLines[i], true); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) + totalChars = totalChars + NFDFileLines[i].length(); + return totalChars; + } + }; + } + + PerfTest.Function TestJDK_NFC_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) + normalizerTest(NFCFileLines[i], true); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) + totalChars = totalChars + NFCFileLines[i].length(); + return totalChars; + } + }; + } + + PerfTest.Function TestJDK_NFC_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) + normalizerTest(fileLines[i], true); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) + totalChars = totalChars + fileLines[i].length(); + return totalChars; + } + }; + } + + // Test NFD Performance + PerfTest.Function TestJDK_NFD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) + normalizerTest(NFDFileLines[i], false); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) + totalChars = totalChars + NFDFileLines[i].length(); + return totalChars; + } + }; + } + + PerfTest.Function TestJDK_NFD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) + normalizerTest(NFCFileLines[i], false); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) + totalChars = totalChars + NFCFileLines[i].length(); + return totalChars; + } + }; + } + + PerfTest.Function TestJDK_NFD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) + normalizerTest(fileLines[i], false); + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) + totalChars = totalChars + fileLines[i].length(); + return totalChars; + } + }; + } + // Test FCD Performance + PerfTest.Function TestICU_FCD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.normalize(NFDFileLines[i], Normalizer.FCD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_FCD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.normalize(NFCFileLines[i], Normalizer.FCD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestICU_FCD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.normalize(fileLines[i], Normalizer.FCD); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + // Test Quick Check Performance + PerfTest.Function TestQC_NFC_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.quickCheck(NFDFileLines[i], Normalizer.NFC,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_NFC_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.quickCheck(NFCFileLines[i], Normalizer.NFC,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_NFC_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.quickCheck(fileLines[i], Normalizer.NFC,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_NFD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.quickCheck(NFDFileLines[i], Normalizer.NFD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_NFD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.quickCheck(NFCFileLines[i], Normalizer.NFD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_NFD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.quickCheck(fileLines[i], Normalizer.NFD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_FCD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.quickCheck(NFDFileLines[i], Normalizer.FCD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_FCD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.quickCheck(NFCFileLines[i], Normalizer.FCD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestQC_FCD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.quickCheck(fileLines[i], Normalizer.FCD,0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + // Test isNormalized Performance + PerfTest.Function TestIsNormalized_NFC_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.isNormalized(NFDFileLines[i], Normalizer.NFC, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_NFC_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.isNormalized(NFCFileLines[i], Normalizer.NFC, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_NFC_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.isNormalized(fileLines[i], Normalizer.NFC, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_NFD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.isNormalized(NFDFileLines[i], Normalizer.NFD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_NFD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.isNormalized(NFCFileLines[i], Normalizer.NFD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_NFD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.isNormalized(fileLines[i], Normalizer.NFD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_FCD_NFD_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFDFileLines.length; i++) { + Normalizer.isNormalized(NFDFileLines[i], Normalizer.FCD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFDFileLines.length; i++) { + totalChars = totalChars + NFDFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_FCD_NFC_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < NFCFileLines.length; i++) { + Normalizer.isNormalized(NFCFileLines[i], Normalizer.FCD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < NFCFileLines.length; i++) { + totalChars = totalChars + NFCFileLines[i].length(); + } + return totalChars; + } + }; + } + + PerfTest.Function TestIsNormalized_FCD_Orig_Text() { + return new PerfTest.Function() { + public void call() { + for (int i = 0; i < fileLines.length; i++) { + Normalizer.isNormalized(fileLines[i], Normalizer.FCD, 0); + } + } + + public long getOperationsPerIteration() { + int totalChars = 0; + for (int i = 0; i < fileLines.length; i++) { + totalChars = totalChars + fileLines[i].length(); + } + return totalChars; + } + }; + } + + /* + private void printUsage() { + System.out.println("Usage: " + this.getClass().getName() + " [OPTIONS] fileName\n" + + "\t-f or --fileName \tfile to be used as test data\n" + + "\t-s or --sourceDir \tsource directory for files followed by path\n" + + "\t-e or --encoding \tencoding of source files\n" + + "\t-b or --bulkMode \tnormalize whole file at once\n" + + "\t-l or --lineMode \tnormalize file one line at a time\n" + ); + System.exit(1); + } + */ + + String[] normalizeInput(String[] src, Normalizer.Mode mode) { + String[] dest = new String[src.length]; + for (int i = 0; i < src.length; i++) { + dest[i] = Normalizer.normalize(src[i], mode); + } + + return dest; + } + + /* + void normalizerInit(boolean compose) { + Class normalizer; + boolean sun; + + try { + normalizer = Class.forName("java.text.Normalizer"); + sun = false; + } catch (ClassNotFoundException ex) { + try { + normalizer = Class.forName("sun.text.Normalizer"); + sun = true; + } catch (ClassNotFoundException ex2) { + throw new RuntimeException( + "Could not find sun.text.Normalizer nor java.text.Normalizer and their required subclasses"); + } + } + + try { + if (sun) { + normalizerArgs = new Object[] { null, null, new Integer(0) }; + normalizerArgs[1] = normalizer.getField(compose ? "COMPOSE" : "DECOMP").get(null); + normalizerMethod = normalizer.getMethod("normalize", new Class[] { String.class, normalizerArgs[1].getClass(), int.class }); + // sun.text.Normalizer.normalize(line, compose + // ? sun.text.Normalizer.COMPOSE + // : sun.text.Normalizer.DECOMP, 0); + } else { + normalizerArgs = new Object[] { null, null }; + normalizerArgs[1] = Class.forName("java.text.Normalizer$Form").getField(compose ? "NFC" : "NFD").get(null); + normalizerMethod = normalizer.getMethod("normalize", new Class[] { CharSequence.class, normalizerArgs[1].getClass()}); + // java.text.Normalizer.normalize(line, compose + // ? java.text.Normalizer.Form.NFC + // : java.text.Normalizer.Form.NFD); + } + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException("Reflection error -- could not load the JDK normalizer (" + normalizer.getName() + ")"); + } + } + + void normalizerTest(String line) { + try { + normalizerArgs[0] = line; + normalizerMethod.invoke(line, normalizerArgs); + } catch (Exception ex) { + if (ex instanceof InvocationTargetException) { + Throwable cause = ex.getCause(); + cause.printStackTrace(); + throw new RuntimeException(cause.getMessage()); + } else { + throw new RuntimeException("Reflection error -- could not run the JDK normalizer"); + } + } + } + */ + + void normalizerTest(String line, boolean compose) { +// sun.text.Normalizer.normalize(line, compose +// ? sun.text.Normalizer.COMPOSE +// : sun.text.Normalizer.DECOMP, 0); + java.text.Normalizer.normalize(line, compose + ? java.text.Normalizer.Form.NFC + : java.text.Normalizer.Form.NFD); + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/PerfTest.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/PerfTest.java new file mode 100644 index 000000000..9e9cef99e --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/PerfTest.java @@ -0,0 +1,961 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + ********************************************************************** + * Copyright (c) 2002-2008, International Business Machines + * Corporation and others. All Rights Reserved. + ********************************************************************** + */ +package com.ibm.icu.dev.test.perf; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PushbackInputStream; +import java.io.Reader; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import com.ibm.icu.dev.tool.shared.UOption; +import com.ibm.icu.impl.LocaleUtility; + +/** + * Base class for performance testing framework. To use, the subclass can simply + * define one or more instance methods with names beginning with "test" (case + * ignored). The prototype of the method is + * + * PerfTest.Function testTheName() + * + * The actual performance test will execute on the returned Command object + * (refer to Command Pattern). To call a test from command line, the 'test' + * prefix of the test method name can be ignored/removed. + * + * In addition, the subclass should define a main() method that calls + * PerfTest.run() as defined here. + * + * If the subclasses uses any command line arguments (beyond those handled + * automatically by this class) then it should override PerfTest.setup() to + * handle its arguments. If the subclasses needs more sophisticated management + * for controlling finding/calling test method, it can replace the default + * implementation for PerfTest.testProvider before calling PerfTest.run(). + * + * Example invocation: java -cp classes -verbose:gc + * com.ibm.icu.dev.test.perf.UnicodeSetPerf --gc --passes 4 --iterations 100 + * UnicodeSetAdd [[:l:][:c:]] + * + * Example output: [GC 511K->192K(1984K), 0.0086170 secs] [GC 704K->353K(1984K), + * 0.0059619 secs] [Full GC 618K->371K(1984K), 0.0242779 secs] [Full GC + * 371K->371K(1984K), 0.0228649 secs] = testUnicodeSetAdd begin 100 = + * testUnicodeSetAdd end 11977 1109044 = testUnicodeSetAdd begin 100 = + * testUnicodeSetAdd end 12047 1109044 = testUnicodeSetAdd begin 100 = + * testUnicodeSetAdd end 11987 1109044 = testUnicodeSetAdd begin 100 = + * testUnicodeSetAdd end 11978 1109044 + * + * The [] lines are emitted by the JVM as a result of the -verbose:gc switch. + * + * Lines beginning with '=' are emitted by PerfTest: = testUnicodeSetAdd begin + * 100 A 'begin' statement contains the name of the setup method, which + * determines what test function is measures, and the number of iterations that + * will be times. = testUnicodeSetAdd end 12047 1109044 An 'end' statement gives + * the name of the setup method again, and then two integers. The first is the + * total elapsed time in milliseconds, and the second is the number of events + * per iteration. In this example, the time per event is 12047 / (100 * 1109044) + * or 108.6 ns/event. + * + * Raw times are given as integer ms, because this is what the system measures. + * + * @author Alan Liu + * @since ICU 2.4 + */ +public abstract class PerfTest { + // Command-line options set these: + protected boolean verbose; + protected String sourceDir; + protected String fileName; + + // protected String resolvedFileName; + protected String encoding; + protected String testName; + protected boolean uselen; + protected int iterations; + protected int passes; + protected int time; + protected boolean line_mode; + protected boolean bulk_mode; + protected Locale locale; + protected boolean doPriorGC; + protected int threads; + protected int duration; + protected boolean action; + + protected TestCmdProvider testProvider = new TestPrefixProvider(this); + + static interface TestCmdProvider { + /** + * @return The names for all available test. + */ + public Set getAllTestCmdNames(); + + /** + * @param name + * @return Whether the given name is a test name. The implementation may + * have more sophisticated naming control here. + * TestCmdProvider.isTestCmd() != Set.contains() + */ + public boolean isTestCmd(String name); + + /** + * @param name + * @return the test Command or null + */ + public PerfTest.Function getTestCmd(String name); + } + + /** + * Treat all method beginning with 'test' prefix (ignoring case) for given + * object as the test methods. + */ + static class TestPrefixProvider implements TestCmdProvider { + private Map theTests = null; // Map<string(no case), string(with case)> + private Set orgNames = null; // shadow reference, ==theTests, for better output + private Object refer; + + TestPrefixProvider(Object theProvider) { + refer = theProvider; + } + + public Set getAllTestCmdNames() { + if (theTests == null) { + theTests = new HashMap(); + orgNames = new HashSet(); + Method[] methods = refer.getClass().getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + String org = methods[i].getName(); + String name = org.toLowerCase(); // ignoring case + // beginning with 'test' + // Note: methods named 'test()' are ignored + if (name.length() > 4 && name.startsWith("test")) { + if (theTests.containsKey(name)) { + throw new Error( + "Duplicate method name ignoring case: " + + name); + } + theTests.put(name, org); + orgNames.add(org); + } + } + } + return orgNames; // beginning with 'test', keeping case + } + + /** + * The given name will map to a method of the same name, or a method + * named "test" + name. Case is ignored. + */ + private String isTestCmd_impl(String name) { + getAllTestCmdNames(); + String tn1 = name.toLowerCase(); + String tn2 = "test" + tn1; + if (theTests.containsKey(tn1)) { + return tn1; + } else if (theTests.containsKey(tn2)) { + return tn2; + } + return null; + } + + public boolean isTestCmd(String name) { + return isTestCmd_impl(name) != null; + } + + public Function getTestCmd(String aname) { + String name = (String) theTests.get(isTestCmd_impl(aname)); + if (name == null) { + return null; + } + + try { + Method m = refer.getClass().getDeclaredMethod(name, + (Class[]) null); + return (Function) m.invoke(refer, new Object[] {}); + } catch (Exception e) { + throw new Error( + "TestPrefixProvider implementation error. Finding: " + + name, e); + } + } + } + + /** + * Subclasses of PerfTest will need to create subclasses of Function that + * define a call() method which contains the code to be timed. They then + * call setTestFunction() in their "Test..." method to establish this as the + * current test functor. + */ + public abstract static class Function { + + /** + * Subclasses should implement this method to do the action to be + * measured if the action is thread-safe + */ + public void call() { call(0); } + + /** + * Subclasses should implement this method if the action is not thread-safe + */ + public void call(int i) { call(); } + + /** + * Subclasses may implement this method to return positive integer + * indicating the number of operations in a single call to this object's + * call() method. If subclasses do not override this method, the default + * implementation returns 1. + */ + public long getOperationsPerIteration() { + return 1; + } + + /** + * Subclasses may implement this method to return either positive or + * negative integer indicating the number of events in a single call to + * this object's call() method. If subclasses do not override this + * method, the default implementation returns -1, indicating that events + * are not applicable to this test. e.g: Number of breaks / iterations + * for break iterator + */ + public long getEventsPerIteration() { + return -1; + } + + /** + * Call call() n times in a tight loop and return the elapsed + * milliseconds. If n is small and call() is fast the return result may + * be zero. Small return values have limited meaningfulness, depending + * on the underlying VM and OS. + */ + public final long time(long n) { + long start, stop; + start = System.currentTimeMillis(); + while (n-- > 0) { + call(); + } + stop = System.currentTimeMillis(); + return stop - start; // ms + } + + + /** + * init is called each time before looping through call + */ + public void init() {} + + + public final int getID() { + return id; + } + + public final void setID(int id) { + this.id = id; + } + + private int id; + } + + private class FunctionRunner implements Runnable { + public FunctionRunner(Function f, long loops, int id) { + this.f = f; + this.loops = loops; + this.id = id; + } + + public void run() { + long n = loops; + while (n-- > 0) + f.call(id); + } + + private Function f; + + private long loops; + private int id; + } + + + /** + * Exception indicating a usage error. + */ + public static class UsageException extends Exception { + /** + * For serialization + */ + private static final long serialVersionUID = -1201256240606806242L; + + public UsageException(String message) { + super(message); + } + + public UsageException() { + super(); + } + } + + /** + * Constructor. + */ + protected PerfTest() { + } + + /** + * Framework method. Default implementation does not parse any extra + * arguments. Subclasses may override this to parse extra arguments. + * Subclass implementations should NOT call the base class implementation. + */ + protected void setup(String[] args) { + if (args.length > 0) { + throw new RuntimeException("Extra arguments received"); + } + } + + /** + * These must be kept in sync with getOptions(). + */ + static final int HELP1 = 0; + static final int HELP2 = 1; + static final int VERBOSE = 2; + static final int SOURCEDIR = 3; + static final int ENCODING = 4; + static final int USELEN = 5; + static final int FILE_NAME = 6; + static final int PASSES = 7; + static final int ITERATIONS = 8; + static final int TIME = 9; + static final int LINE_MODE = 10; + static final int BULK_MODE = 11; + static final int LOCALE = 12; + static final int TEST_NAME = 13; + static final int THREADS = 14; + static final int DURATION = 15; + static final int ACTION = 16; + + // Options above here are identical to those in C; keep in sync with C + // Options below here are unique to Java; shift down as necessary + static final int GARBAGE_COLLECT = 17; + static final int LIST = 18; + + UOption[] getOptions() { + return new UOption[] { + UOption.HELP_H(), + UOption.HELP_QUESTION_MARK(), + UOption.VERBOSE(), + UOption.SOURCEDIR(), + UOption.ENCODING(), + UOption.DEF("uselen", 'u', UOption.NO_ARG), + UOption.DEF("filename", 'f', UOption.REQUIRES_ARG), + UOption.DEF("passes", 'p', UOption.REQUIRES_ARG), + UOption.DEF("iterations", 'i', UOption.REQUIRES_ARG), + UOption.DEF("time", 't', UOption.REQUIRES_ARG), + UOption.DEF("line-mode", 'l', UOption.NO_ARG), + UOption.DEF("bulk-mode", 'b', UOption.NO_ARG), + UOption.DEF("locale", 'L', UOption.REQUIRES_ARG), + UOption.DEF("testname", 'T', UOption.REQUIRES_ARG), + UOption.DEF("threads", 'r', UOption.REQUIRES_ARG), + UOption.DEF("duration", 'd', UOption.NO_ARG), + UOption.DEF("action", 'a', UOption.NO_ARG), + + // Options above here are identical to those in C; keep in sync + // Options below here are unique to Java + + UOption.DEF("gc", 'g', UOption.NO_ARG), + UOption.DEF("list", (char) -1, UOption.NO_ARG), }; + } + + /** + * Subclasses should call this method in their main(). run() will in turn + * call setup() with any arguments it does not parse. This method parses the + * command line and runs the tests given on the command line, with the given + * parameters. See the class description for details. + */ + protected final void run(String[] args) throws Exception { + Set testList = parseOptions(args); + + // Run the tests + for (Iterator iter = testList.iterator(); iter.hasNext();) { + String meth = (String) iter.next(); + + // Call meth to set up the test + // long eventsPerCall = -1; + Function testFunction = testProvider.getTestCmd(meth); + if (testFunction == null) { + throw new RuntimeException(meth + + " failed to return a test function"); + } + long ops = testFunction.getOperationsPerIteration(); + if (ops < 1) { + throw new RuntimeException(meth + + " returned an illegal operations/iteration()"); + } + + long min_t = 1000000; + long t; + // long b = System.currentTimeMillis(); + long calibration_iter = getIteration(meth, testFunction); + // System.out.println("The guess cost: " + (System.currentTimeMillis() - b)/1000. + " s."); + + // Calculate iterations for the specified duration/pass. + double timePerIter = performLoops(testFunction, calibration_iter)/1000./calibration_iter; + long iterationCount = (long) (duration/timePerIter + 0.5); + + for (int j = 0; j < passes; ++j) { + long events = -1; + if (verbose) { + if (iterations > 0) { + System.out.println("= " + meth + " begin " + iterations); + } else { + System.out.println("= " + meth + " begin " + time + " seconds"); + } + } else if (!action) { + System.out.println("= " + meth + " begin "); + } + + t = performLoops(testFunction, iterationCount); + if (t < min_t) { + min_t = t; + } + events = testFunction.getEventsPerIteration(); + + if (verbose) { + if (events == -1) { + System.out.println("= " + meth + " end " + (t / 1000.0) + " loops: " + iterationCount + " operations: " + + ops); + } else { + System.out.println("= " + meth + " end " + (t / 1000.0) + " loops: " + iterationCount + " operations: " + + ops + " events: " + events); + } + } else if (!action) { + if (events == -1) { + System.out.println("= " + meth + " end " + (t / 1000.0) + " " + iterationCount + " " + ops); + } else { + System.out.println("= " + meth + " end " + (t / 1000.0) + " " + iterationCount + " " + + ops + " " + events); + } + } + } + if (action) { + // Print results in ndjson format for GHA Benchmark to process. + System.out.println("{\"biggerIsBetter\":false,\"name\":\"" + meth + + "\",\"unit\":\"ns/iter\",\"value\":" + (min_t*1E6) / (iterationCount*ops) + "}"); + } + } + } + + /** + * @param args + * @return the method list to call + * @throws UsageException + */ + private Set parseOptions(String[] args) throws UsageException { + + doPriorGC = false; + encoding = ""; + uselen = false; + fileName = null; + sourceDir = null; + line_mode = false; + verbose = false; + bulk_mode = false; + passes = iterations = time = -1; + locale = null; + testName = null; + threads = 1; + duration = 10; // Default used by Perl scripts + action = false; // If test is invoked on command line, includes GitHub Action + + UOption[] options = getOptions(); + int remainingArgc = UOption.parseArgs(args, options); + + if (args.length == 0 || options[HELP1].doesOccur || options[HELP2].doesOccur) + throw new UsageException(); + + if (options[LIST].doesOccur) { + System.err.println("Available tests:"); + Set testNames = testProvider.getAllTestCmdNames(); + for (Iterator iter = testNames.iterator(); iter.hasNext();) { + String name = (String) iter.next(); + System.err.println(" " + name); + } + System.exit(0); + } + + if (options[TIME].doesOccur && options[ITERATIONS].doesOccur) + throw new UsageException("Cannot specify both '-t <seconds>' and '-i <iterations>'"); + else if (!options[TIME].doesOccur && !options[ITERATIONS].doesOccur) + throw new UsageException("Either '-t <seconds>' or '-i <iterations>' must be specified"); + else if (options[ITERATIONS].doesOccur) { + try { + iterations = Integer.parseInt(options[ITERATIONS].value); + } catch (NumberFormatException ex) { + throw new UsageException("'-i <iterations>' requires an integer number of iterations"); + } + } else { //if (options[TIME].doesOccur) + try { + time = Integer.parseInt(options[TIME].value); + } catch (NumberFormatException ex) { + throw new UsageException("'-r <seconds>' requires an integer number of seconds"); + } + } + + if (!options[PASSES].doesOccur) + throw new UsageException("'-p <passes>' must be specified"); + else + passes = Integer.parseInt(options[PASSES].value); + + if (options[LINE_MODE].doesOccur && options[BULK_MODE].doesOccur) + throw new UsageException("Cannot specify both '-l' (line mode) and '-b' (bulk mode)"); + + if (options[THREADS].doesOccur) { + try { + threads = Integer.parseInt(options[THREADS].value); + } catch (NumberFormatException ex) { + throw new UsageException("'-r <threads>' requires an integer number of threads"); + } + if (threads <= 0) + throw new UsageException("'-r <threads>' requires an number of threads greater than 0"); + } + if (options[DURATION].doesOccur) { + try { + duration = Integer.parseInt(options[DURATION].value); + } catch (NumberFormatException ex) { + throw new UsageException("'-d <duration>' requires an integer number of threads"); + } + } + + line_mode = options[LINE_MODE].doesOccur; + bulk_mode = options[BULK_MODE].doesOccur; + verbose = options[VERBOSE].doesOccur; + uselen = options[USELEN].doesOccur; + doPriorGC = options[GARBAGE_COLLECT].doesOccur; + action = options[ACTION].doesOccur; + + if (options[SOURCEDIR].doesOccur) sourceDir = options[SOURCEDIR].value; + if (options[ENCODING].doesOccur) encoding = options[ENCODING].value; + if (options[FILE_NAME].doesOccur) fileName = options[FILE_NAME].value; + if (options[TEST_NAME].doesOccur) testName = options[TEST_NAME].value; + if (options[LOCALE].doesOccur) locale = LocaleUtility.getLocaleFromName(options[LOCALE].value); + + + // build the test list + Set testList = new HashSet(); + int i, j; + for (i = 0; i < remainingArgc; ++i) { + // is args[i] a method name? + if (testProvider.isTestCmd(args[i])) { + testList.add(args[i]); + } else { + // args[i] is neither a method name nor a number. Pass + // everything from here on through to the subclass via + // setup(). + break; + } + } + + // if no tests were specified, put all the tests in the test list + if (testList.size() == 0) { + Set testNames = testProvider.getAllTestCmdNames(); + Iterator iter = testNames.iterator(); + while (iter.hasNext()) + testList.add((String)iter.next()); + } + + // pass remaining arguments, if any, through to the subclass via setup() method. + String[] subclassArgs = new String[remainingArgc - i]; + for (j = 0; i < remainingArgc; j++) + subclassArgs[j] = args[i++]; + setup(subclassArgs); + + // Put the heap in a consistent state + if (doPriorGC) + gc(); + + return testList; + } + + /** + * Translate '-t time' to iterations (or just return '-i iteration') + * + * @param meth + * @param fn + * @return rt + */ + private long getIteration(String methName, Function fn) throws InterruptedException { + long iter = 0; + if (iterations > 0) { + iter = iterations; + } else { // iterations not in input, calibrate iterations for given time. + // Translate time to iteration + // Assuming there is a linear relation between time and iterations + + if (verbose) { + System.out.println("= " + methName + " calibrating " + time + + " seconds"); + } + + long base = time * 1000; + // System.out.println("base :" + base); + long seed = 1; + long t = 0; + while (t < base * 0.9 || base * 1.1 < t) { // + - 10% + if (iter == 0 || t == 0) { + iter = seed; // start up from 1 + seed *= 100; // if the method is too fast (t == 0), + // multiply 100 times + // 100 is rational because 'base' is always larger than 1000 + } else { + // If 't' is large enough, use linear function to calculate + // new iteration + // + // new iter(base) old iter + // -------------- = -------- = k + // new time old time + // + // System.out.println("before guess t: " + t); + // System.out.println("before guess iter: " + iter); + iter = (long) ((double) iter / t * base); // avoid long + // cut, eg. 1/10 + // == 0 + if (iter == 0) { + throw new RuntimeException( + "Unable to converge on desired duration"); + } + } + t = performLoops(fn, iter); + } + // System.out.println("final t : " + t); + // System.out.println("final i : " + iter); + } + return iter; + } + + + private long performLoops(Function function, long loops) throws InterruptedException { + function.init(); + if (threads > 1) { + Thread[] threadList = new Thread[threads]; + for (int i=0; i<threads; i++) + threadList[i] = new Thread(new FunctionRunner(function, loops, i)); + + long start = System.currentTimeMillis(); + for (int i=0; i<threads; i++) + threadList[i].start(); + for (int i=0; i<threads; i++) + threadList[i].join(); + return System.currentTimeMillis() - start; + + } else { + return function.time(loops); // ms + } + } + + + /** + * Invoke the runtime's garbage collection procedure repeatedly until the + * amount of free memory stabilizes to within 10%. + */ + protected void gc() { + if (false) { + long last; + long free = 1; + Runtime runtime = Runtime.getRuntime(); + do { + runtime.gc(); + last = free; + free = runtime.freeMemory(); + } while (((double) Math.abs(free - last)) / free > 0.1); + // Wait for the change in free memory to drop under 10% + // between successive calls. + } + + // From "Java Platform Performance". This is the procedure + // recommended by Javasoft. + try { + System.gc(); + Thread.sleep(100); + System.runFinalization(); + Thread.sleep(100); + + System.gc(); + Thread.sleep(100); + System.runFinalization(); + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + + + public static char[] readToEOS(Reader reader) { + ArrayList vec = new ArrayList(); + int count = 0; + int pos = 0; + final int MAXLENGTH = 0x8000; // max buffer size - 32K + int length = 0x80; // start with small buffers and work up + do { + pos = 0; + length = length >= MAXLENGTH ? MAXLENGTH : length * 2; + char[] buffer = new char[length]; + try { + do { + int n = reader.read(buffer, pos, length - pos); + if (n == -1) { + break; + } + pos += n; + } while (pos < length); + } + catch (IOException e) { + } + vec.add(buffer); + count += pos; + } while (pos == length); + + char[] data = new char[count]; + pos = 0; + for (int i = 0; i < vec.size(); ++i) { + char[] buf = (char[]) vec.get(i); + int len = Math.min(buf.length, count - pos); + System.arraycopy(buf, 0, data, pos, len); + pos += len; + } + return data; + } + public static byte[] readToEOS(InputStream stream) { + + ArrayList vec = new ArrayList(); + int count = 0; + int pos = 0; + final int MAXLENGTH = 0x8000; // max buffer size - 32K + int length = 0x80; // start with small buffers and work up + do { + pos = 0; + length = length >= MAXLENGTH ? MAXLENGTH : length * 2; + byte[] buffer = new byte[length]; + try { + do { + int n = stream.read(buffer, pos, length - pos); + if (n == -1) { + break; + } + pos += n; + } while (pos < length); + } + catch (IOException e) { + } + vec.add(buffer); + count += pos; + } while (pos == length); + + + byte[] data = new byte[count]; + pos = 0; + for (int i = 0; i < vec.size(); ++i) { + byte[] buf = (byte[]) vec.get(i); + int len = Math.min(buf.length, count - pos); + System.arraycopy(buf, 0, data, pos, len); + pos += len; + } + return data; + } + + protected String[] readLines(String filename, String srcEncoding, boolean bulkMode) { + FileInputStream fis = null; + InputStreamReader isr = null; + BufferedReader br = null; + try { + fis = new FileInputStream(filename); + isr = new InputStreamReader(fis, srcEncoding); + br = new BufferedReader(isr); + } catch (Exception e) { + System.err.println("Error: File access exception: " + e.getMessage() + "!"); + System.exit(1); + } + ArrayList list = new ArrayList(); + while (true) { + String line = null; + try { + line = readDataLine(br); + } catch (Exception e) { + System.err.println("Read File Error" + e.getMessage() + "!"); + System.exit(1); + } + if (line == null) break; + if (line.length() == 0) continue; + list.add(line); + } + + int size = list.size(); + String[] lines = null; + + if (bulkMode) { + lines = new String[1]; + StringBuffer buffer = new StringBuffer(""); + for (int i = 0; i < size; ++i) { + buffer.append((String) list.get(i)); + /*if (i < (size - 1)) { + buffer.append("\r\n"); + }*/ + } + lines[0] = buffer.toString(); + } else { + lines = new String[size]; + for (int i = 0; i < size; ++i) { + lines[i] = (String) list.get(i); + } + } + + return lines; + } + + public String readDataLine(BufferedReader br) throws Exception { + String originalLine = ""; + String line = ""; + try { + line = originalLine = br.readLine(); + if (line == null) return null; + if (line.length() > 0 && line.charAt(0) == 0xFEFF) line = line.substring(1); + int commentPos = line.indexOf('#'); + if (commentPos >= 0) line = line.substring(0, commentPos); + line = line.trim(); + } catch (Exception e) { + throw new Exception("Line \"{0}\", \"{1}\"" + originalLine + " " + + line + " " + e.toString()); + } + return line; + } + + + public static class BOMFreeReader extends Reader { + InputStreamReader reader; + String encoding; + int MAX_BOM_LENGTH = 5; + + /** + * Creates a new reader, skipping a BOM associated with the given + * encoding. Equivalent to BOMFreeReader(in, null). + * + * @param in + * The input stream. + * @throws IOException + * Thrown if reading for a BOM causes an IOException. + */ + public BOMFreeReader(InputStream in) throws IOException { + this(in, null); + } + + /** + * Creates a new reader, skipping a BOM associated with the given + * encoding. If encoding is null, attempts to detect the encoding by the + * BOM. + * + * @param in + * The input stream. + * @param encoding + * The encoding to use. Can be null. + * @throws IOException + * Thrown if reading for a BOM causes an IOException. + */ + public BOMFreeReader(InputStream in, String encoding) throws IOException { + PushbackInputStream pushback = new PushbackInputStream(in, MAX_BOM_LENGTH); + this.encoding = encoding; + + byte[] start = new byte[MAX_BOM_LENGTH]; + Arrays.fill(start, (byte)0xa5); + + int amountRead = pushback.read(start, 0, MAX_BOM_LENGTH); + int bomLength = detectBOMLength(start); + if (amountRead > bomLength) + pushback.unread(start, bomLength, amountRead - bomLength); + + reader = (encoding == null) ? new InputStreamReader(pushback) : new InputStreamReader(pushback, encoding); + } + + /** + * Determines the length of a BOM in the beginning of start. Assumes + * start is at least a length 5 array. If encoding is null, the check + * will not be encoding specific and it will set the encoding of this + * BOMFreeReader. + * + * @param start + * The starting bytes. + * @param encoding + * The encoding. Can be null. + * @return The length of a detected BOM. + */ + private int detectBOMLength(byte[] start) { + if ((encoding == null || "UTF-16BE".equals(encoding)) && start[0] == (byte) 0xFE && start[1] == (byte) 0xFF) { + if (encoding == null) this.encoding = "UTF-16BE"; + return 2; // "UTF-16BE"; + } else if (start[0] == (byte) 0xFF && start[1] == (byte) 0xFE) { + if ((encoding == null || "UTF-32LE".equals(encoding)) && start[2] == (byte) 0x00 + && start[3] == (byte) 0x00) { + if (encoding == null) this.encoding = "UTF-32LE"; + return 4; // "UTF-32LE"; + } else if ((encoding == null || "UTF-16LE".equals(encoding))) { + if (encoding == null) this.encoding = "UTF-16LE"; + return 2; // "UTF-16LE"; + } + } else if ((encoding == null || "UTF-8".equals(encoding)) && start[0] == (byte) 0xEF + && start[1] == (byte) 0xBB && start[2] == (byte) 0xBF) { + if (encoding == null) this.encoding = "UTF-8"; + return 3; // "UTF-8"; + } else if ((encoding == null || "UTF-32BE".equals(encoding)) && start[0] == (byte) 0x00 + && start[1] == (byte) 0x00 && start[2] == (byte) 0xFE && start[3] == (byte) 0xFF) { + if (encoding == null) this.encoding = "UTF-32BE"; + return 4; // "UTF-32BE"; + } else if ((encoding == null || "SCSU".equals(encoding)) && start[0] == (byte) 0x0E + && start[1] == (byte) 0xFE && start[2] == (byte) 0xFF) { + if (encoding == null) this.encoding = "SCSU"; + return 3; // "SCSU"; + } else if ((encoding == null || "BOCU-1".equals(encoding)) && start[0] == (byte) 0xFB + && start[1] == (byte) 0xEE && start[2] == (byte) 0x28) { + if (encoding == null) this.encoding = "BOCU-1"; + return 3; // "BOCU-1"; + } else if ((encoding == null || "UTF-7".equals(encoding)) && start[0] == (byte) 0x2B + && start[1] == (byte) 0x2F && start[2] == (byte) 0x76) { + if (start[3] == (byte) 0x38 && start[4] == (byte) 0x2D) { + if (encoding == null) this.encoding = "UTF-7"; + return 5; // "UTF-7"; + } else if (start[3] == (byte) 0x38 || start[3] == (byte) 0x39 || start[3] == (byte) 0x2B + || start[3] == (byte) 0x2F) { + if (encoding == null) this.encoding = "UTF-7"; + return 4; // "UTF-7"; + } + } else if ((encoding == null || "UTF-EBCDIC".equals(encoding)) && start[0] == (byte) 0xDD + && start[2] == (byte) 0x73 && start[2] == (byte) 0x66 && start[3] == (byte) 0x73) { + if (encoding == null) this.encoding = "UTF-EBCDIC"; + return 4; // "UTF-EBCDIC"; + } + + /* no known Unicode signature byte sequence recognized */ + return 0; + } + + public int read(char[] cbuf, int off, int len) throws IOException { + return reader.read(cbuf, off, len); + } + + public void close() throws IOException { + reader.close(); + } + } +} + + + +// eof diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/RBBIPerf.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/RBBIPerf.java new file mode 100644 index 000000000..342f7a51d --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/RBBIPerf.java @@ -0,0 +1,161 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (c) 2002-2004, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +package com.ibm.icu.dev.test.perf; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.BreakIterator; + +import com.ibm.icu.text.RuleBasedBreakIterator; +import com.ibm.icu.text.UTF16; + +/** + * A class for testing UnicodeSet performance. + * + * @author Alan Liu + * @since ICU 2.4 + */ +public class RBBIPerf extends PerfTest { + + String dataFileName; + RuleBasedBreakIterator bi; + BreakIterator jdkbi; + String testString; + + public static void main(String[] args) throws Exception { + new RBBIPerf().run(args); + } + + protected void setup(String[] args) { + // We only take one argument, the pattern + if (args.length != 2) { + throw new RuntimeException("RBBITest params: data_file_name break_iterator_type "); + } + + try { + dataFileName = args[0]; + StringBuffer testFileBuf = new StringBuffer(); + InputStream is = new FileInputStream(dataFileName); + InputStreamReader isr = new InputStreamReader(is, "UTF-8"); + int c; + for (;;) { + c = isr.read(); + if (c < 0) { + break; + } + UTF16.append(testFileBuf, c); + } + testString = testFileBuf.toString(); + } + catch (IOException e) { + throw new RuntimeException(e.toString()); + } + + if (args.length >= 2) { + if (args[1].equals("char")) { + bi = (RuleBasedBreakIterator)com.ibm.icu.text.BreakIterator.getCharacterInstance(); + } else if (args[1].equals("word")) { + bi = (RuleBasedBreakIterator)com.ibm.icu.text.BreakIterator.getWordInstance(); + } else if (args[1].equals("line")) { + bi = (RuleBasedBreakIterator)com.ibm.icu.text.BreakIterator.getLineInstance(); + } else if (args[1].equals("jdkline")) { + jdkbi = BreakIterator.getLineInstance(); + } + } + if (bi!=null ) { + bi.setText(testString); + } + if (jdkbi != null) { + jdkbi.setText(testString); + } + + } + + + + PerfTest.Function testRBBINext() { + return new PerfTest.Function() { + + public void call() { + int n; + if (bi != null) { + n = bi.first(); + for (; n != BreakIterator.DONE; n=bi.next()) { + } + } else { + n = jdkbi.first(); + for (; n != BreakIterator.DONE; n=jdkbi.next()) { + } + } + } + + + public long getOperationsPerIteration() { + int n; + int count = 0; + if (bi != null) { + for (n=bi.first(); n != BreakIterator.DONE; n=bi.next()) { + count++; + } + } else { + for (n=jdkbi.first(); n != BreakIterator.DONE; n=jdkbi.next()) { + count++; + } + } + return count; + } + }; + } + + + PerfTest.Function testRBBIPrevious() { + return new PerfTest.Function() { + + public void call() { + bi.first(); + int n=0; + for (n=bi.last(); n != BreakIterator.DONE; n=bi.previous()) { + } + } + + + public long getOperationsPerIteration() { + int n; + int count = 0; + for (n=bi.last(); n != BreakIterator.DONE; n=bi.previous()) { + count++; + } + return count; + } + }; + } + + + PerfTest.Function testRBBIIsBoundary() { + return new PerfTest.Function() { + + public void call() { + int n=testString.length(); + int i; + for (i=0; i<n; i++) { + bi.isBoundary(i); + } + } + + public long getOperationsPerIteration() { + int n = testString.length(); + return n; + } + }; + } + + + +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ResourceBundlePerf.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ResourceBundlePerf.java new file mode 100644 index 000000000..24ebd4fe7 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ResourceBundlePerf.java @@ -0,0 +1,374 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (c) 2006-2008, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ + +package com.ibm.icu.dev.test.perf; + +import java.nio.ByteBuffer; +import java.util.ResourceBundle; + +import com.ibm.icu.util.UResourceBundle; + +public class ResourceBundlePerf extends PerfTest { + + private UResourceBundle icuRes = null; + private ResourceBundle javaRes = null; + + public static void main(String[] org_args) throws Exception { + new ResourceBundlePerf().run(org_args); + } + + protected void setup(String[] args) { + icuRes = UResourceBundle.getBundleInstance("com/ibm/icu/dev/data/testdata", "testtypes"); + javaRes = ResourceBundle.getBundle("com.ibm.icu.dev.data.TestDataElements_testtypes"); + } + + PerfTest.Function TestResourceBundleConstructionJava() { + return new PerfTest.Function() { + public void call() { + javaRes = ResourceBundle.getBundle("com.ibm.icu.dev.data.TestDataElements_testtypes"); + } + }; + } + PerfTest.Function TestResourceBundleConstructionICU() { + return new PerfTest.Function() { + public void call() { + UResourceBundle.getBundleInstance("com/ibm/icu/dev/data/testdata", "testtypes"); + } + }; + } + + PerfTest.Function TestEmptyArrayJava() { + return new PerfTest.Function(){ + public void call(){ + String[] s = javaRes.getStringArray("emptyarray"); + if (s.length != 0) throw new Error ("not zero"); + } + }; + } + + PerfTest.Function TestEmptyArrayICU() { + return new PerfTest.Function(){ + public void call(){ + String[] s = icuRes.getStringArray("emptyarray"); + if (s.length != 0) throw new Error ("not zero"); + } + }; + } + + class GetStringJava extends PerfTest.Function { + String key; + String expected; + GetStringJava(String key, String expected) { + this.key = key; + this.expected = expected; + } + public void call() { + String s = javaRes.getString(key); + if (!s.equals(expected)) throw new Error("not equal"); + } + } + + class GetStringIcu extends PerfTest.Function { + String key; + String expected; + GetStringIcu(String key, String expected) { + this.key = key; + this.expected = expected; + } + public void call() { + String s = icuRes.getString(key); + if (!s.equals(expected)) throw new Error("not equal"); + } + } + + PerfTest.Function TestZeroTestJava(){ + return new GetStringJava("zerotest", "abc\u0000def"); + } + + PerfTest.Function TestZeroTestICU(){ + return new GetStringIcu("zerotest", "abc\u0000def"); + } + + PerfTest.Function TestEmptyExplicitStringJava(){ + return new GetStringJava("emptyexplicitstring", ""); + } + + PerfTest.Function TestEmptyExplicitStringICU(){ + return new GetStringIcu("emptyexplicitstring", ""); + } + + PerfTest.Function TestEmptyStringJava(){ + return new GetStringJava("emptystring", ""); + } + + PerfTest.Function TestEmptyStringICU(){ + return new GetStringIcu("emptystring", ""); + } + + class GetIntJava extends PerfTest.Function { + String key; + int expected; + GetIntJava(String key, int expected) { + this.key = key; + this.expected = expected; + } + public void call() { + Integer t = (Integer) javaRes.getObject(key); + if (t.intValue() != expected) throw new Error("not equal"); + } + } + + class GetIntIcu extends PerfTest.Function { + String key; + int expected; + GetIntIcu(String key, int expected) { + this.key = key; + this.expected = expected; + } + public void call() { + UResourceBundle temp = icuRes.get(key); + int t = temp.getInt(); + if (t != expected) throw new Error("not equal"); + } + } + + PerfTest.Function TestGet123Java(){ + return new GetIntJava("onehundredtwentythree", 123); + } + + PerfTest.Function TestGet123ICU(){ + return new GetIntIcu("onehundredtwentythree", 123); + } + + PerfTest.Function TestGetEmptyIntJava(){ + return new GetIntJava("emptyint", 0); + } + + PerfTest.Function TestGetEmptyIntICU(){ + return new GetIntIcu("emptyint", 0); + } + + PerfTest.Function TestGetOneJava(){ + return new GetIntJava("one", 1); + } + + PerfTest.Function TestGetOneICU(){ + return new GetIntIcu("one", 1); + } + + PerfTest.Function TestGetMinusOneJava(){ + return new GetIntJava("minusone", -1); + } + + PerfTest.Function TestGetMinusOneICU(){ + return new GetIntIcu("minusone", -1); + } + + PerfTest.Function TestGetPlusOneJava(){ + return new GetIntJava("plusone", 1); + } + + PerfTest.Function TestGetPlusOneICU(){ + return new GetIntIcu("plusone", 1); + } + + PerfTest.Function TestGetMinusOneUintJava(){ // TODO: no equivalence? + return new PerfTest.Function(){ + public void call(){ + Integer t = (Integer) javaRes.getObject("minusone"); + if (t.intValue() != -1 ) throw new Error("not equal"); + } + }; + } + + PerfTest.Function TestGetMinusOneUintICU(){ + return new PerfTest.Function(){ + public void call(){ + UResourceBundle sub = icuRes.get("minusone"); + int t = sub.getUInt(); + if (t != 0xFFFFFFF) throw new Error("not equal"); + } + }; + } + + + class GetIvJava extends PerfTest.Function { + String key; + int[] expected; + GetIvJava(String key, int[] expected) { + this.key = key; + this.expected = expected; + } + public void call() { + Integer[] iv = (Integer[]) javaRes.getObject(key); + for (int i = 0; i < iv.length; i++){ + if (expected[i] != iv[i].intValue()) throw new Error("not equal"); + } + } + } + + class GetIvIcu extends PerfTest.Function { + String key; + int[] expected; + GetIvIcu(String key, int[] expected) { + this.key = key; + this.expected = expected; + } + public void call() { + UResourceBundle temp = icuRes.get(key); + int[] iv = temp.getIntVector(); + for (int i = 0; i < iv.length; i++){ + if (expected[i] != iv[i]) throw new Error("not equal"); + } + } + } + + PerfTest.Function TestGetIntegerArrayJava(){ + return new GetIvJava("integerarray", new int[]{1,2,3,-3,4,5,6,7}); + } + + PerfTest.Function TestGetIntegerArrayICU(){ + return new GetIvIcu("integerarray", new int[]{1,2,3,-3,4,5,6,7}); + } + + PerfTest.Function TestGetEmptyIntegerArrayJava(){ + return new GetIvJava("emptyintv", new int[0]); + } + + PerfTest.Function TestGetEmptyIntegerArrayICU(){ + return new GetIvIcu("emptyintv", new int[0]); + } + + + class GetBinaryIcu extends PerfTest.Function { + String key; + int expected_len; + GetBinaryIcu(String key, int expected_len) { + this.key = key; + this.expected_len = expected_len; + } + public void call() { + UResourceBundle temp = icuRes.get(key); + ByteBuffer got = temp.getBinary(); + if(got.remaining() != expected_len) throw new Error("not the expected len"); + for(int i=0; i< got.remaining(); i++){ + byte b = got.get(); + if (i != b) throw new Error("not equal"); + } + } + } + + class GetBinaryJava extends PerfTest.Function { + String key; + int expected_len; + GetBinaryJava(String key, int expected_len) { + this.key = key; + this.expected_len = expected_len; + } + public void call() { + ByteBuffer got = ByteBuffer.wrap((byte[])javaRes.getObject(key)); + if(got.remaining() != expected_len) throw new Error("not the expected len"); + for(int i=0; i< got.remaining(); i++){ + byte b = got.get(); + if (i != b) throw new Error("not equal"); + } + } + } + + PerfTest.Function TestGetBinaryTestICU(){ + return new GetBinaryIcu("binarytest", 15); + } + + PerfTest.Function TestGetBinaryTestJava(){ + return new GetBinaryJava("binarytest", 15); + } + + PerfTest.Function TestGetEmptyBinaryICU(){ + return new GetBinaryIcu("emptybin", 0); + } + + PerfTest.Function TestGetEmptyBinaryJava(){ + return new GetBinaryJava("emptybin", 0); + } + + class GetMenuJava extends PerfTest.Function { + String key; + String[] expected; + GetMenuJava(String key, String[] expected) { + this.key = key; + this.expected = expected; + } + public void call() { + int p = 0; + Object[][] menus = (Object[][]) javaRes.getObject(key); + int sizei = menus.length; + for (int i=0; i<sizei; i++){ + String menu_name = (String) menus[i][0]; + Object[][] menu_items = (Object[][]) menus[i][1]; + if (!expected[p++].equals(menu_name)) throw new Error("not equal"); + + int sizej = menu_items.length; + for (int j=0; j< sizej; j++){ + String itemKey = (String) menu_items[j][0]; + String value = (String) menu_items[j][1]; + if(!expected[p++].equals(itemKey)) throw new Error("not equal"); + if(!expected[p++].equals(value)) throw new Error("not equal"); + } + } + + } + } + + class GetMenuIcu extends PerfTest.Function { + String key; + String[] expected; + GetMenuIcu(String key, String[] expected) { + this.key = key; + this.expected = expected; + } + public void call() { + int p = 0; + UResourceBundle menus = icuRes.get(key); + int sizei = menus.getSize(); + for (int i=0; i<sizei; i++){ + UResourceBundle menu = menus.get(i); + String menu_name = menu.getKey(); + if (!expected[p++].equals(menu_name)) throw new Error("not equal"); + + int sizej = menu.getSize(); + for (int j=0; j< sizej; j++){ + UResourceBundle menu_item = menu.get(j); + String itemKey = menu_item.getKey(); + String value = menu_item.getString(); + if(!expected[p++].equals(itemKey)) throw new Error("not equal"); + if(!expected[p++].equals(value)) throw new Error("not equal"); + } + } + + } + } + + PerfTest.Function TestGetMenuJava(){ + String[] expected = new String[]{"file", "exit", "Exit", "open", "Open", "save", "Save"}; + return new GetMenuJava("menu", expected); + } + + PerfTest.Function TestGetMenuICU(){ + String[] expected = new String[]{"file", "exit", "Exit", "open", "Open", "save", "Save"}; + return new GetMenuIcu("menu", expected); + } + + PerfTest.Function TestGetEmptyMenuJava(){ + return new GetMenuJava("emptytable", new String[]{}); + } + + PerfTest.Function TestGetEmptyMenuICU(){ + return new GetMenuIcu("emptytable", new String[]{}); + } +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ServiceObjectCreationPerf.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ServiceObjectCreationPerf.java new file mode 100644 index 000000000..0db4ad184 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ServiceObjectCreationPerf.java @@ -0,0 +1,82 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* + ******************************************************************************* + * Copyright (C) 2014, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.dev.test.perf; + + +/** + * ICU service object creation performance test cases + */ +public class ServiceObjectCreationPerf extends PerfTest { + private static final long DEF_COUNT = 1000L; + + public static void main(String... args) throws Exception { + new ServiceObjectCreationPerf().run(args); + } + + PerfTest.Function TestCalendarJava() { + return new PerfTest.Function() { + private long n = DEF_COUNT; + public void call() { + for (long i = 0; i < n; i++) { + @SuppressWarnings("unused") + java.util.Calendar cal = java.util.Calendar.getInstance(); + } + } + public long getOperationsPerIteration() { + return n; + } + }; + } + + PerfTest.Function TestCalendarICU() { + return new PerfTest.Function() { + private long n = DEF_COUNT; + public void call() { + for (long i = 0; i < n; i++) { + @SuppressWarnings("unused") + com.ibm.icu.util.Calendar cal = com.ibm.icu.util.Calendar.getInstance(); + } + } + public long getOperationsPerIteration() { + return n; + } + }; + } + + PerfTest.Function TestTimeZoneJava() { + return new PerfTest.Function() { + private long n = DEF_COUNT; + public void call() { + for (long i = 0; i < n; i++) { + @SuppressWarnings("unused") + java.util.TimeZone tz = java.util.TimeZone.getDefault(); + } + } + public long getOperationsPerIteration() { + return n; + } + }; + } + + PerfTest.Function TestTimeZoneICU() { + return new PerfTest.Function() { + private long n = DEF_COUNT; + public void call() { + for (long i = 0; i < n; i++) { + @SuppressWarnings("unused") + com.ibm.icu.util.TimeZone tz = com.ibm.icu.util.TimeZone.getDefault(); + } + } + public long getOperationsPerIteration() { + return n; + } + }; + } + +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UCharacterPerf.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UCharacterPerf.java new file mode 100644 index 000000000..4379fda00 --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UCharacterPerf.java @@ -0,0 +1,535 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/** + ******************************************************************************* + * Copyright (C) 2001-2004, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ + +package com.ibm.icu.dev.test.perf; + +import com.ibm.icu.lang.UCharacter; + +/** + * Base performance test that takes in a method name for testing with JDK. + * To use + * <code> + * java com.ibm.icu.dev.test.perf.UCharacterPerf $MethodName $LoopCount - + * $START_TEST_CHARACTER $END_TEST_CHARACTER + * </code> + * where $*_TEST_CHARACTER are in hex decimals with a leading 0x + */ +public final class UCharacterPerf extends PerfTest +{ + // public methods ------------------------------------------------------ + + public static void main(String[] args) throws Exception + { + new UCharacterPerf().run(args); + // new UCharacterPerf().TestPerformance(); + } + + protected void setup(String[] args) { + // We only take one argument, the pattern + MIN_ = Character.MIN_VALUE; + MAX_ = Character.MAX_VALUE; + if (args.length >= 1) { + MIN_ = Integer.parseInt(args[0], 16); + } + if (args.length >= 2) { + MAX_ = Integer.parseInt(args[1], 16); + } + } + + PerfTest.Function testDigit() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.digit(ch, 10); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKDigit() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.digit(ch, 10); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testGetNumericValue() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.getNumericValue(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKGetNumericValue() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.getNumericValue(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testGetType() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.getType(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKGetType() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.getType(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsDefined() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isDefined(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsDefined() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isDefined(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsDigit() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isDigit(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsDigit() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isDigit(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsIdentifierIgnorable() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isIdentifierIgnorable(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsIdentifierIgnorable() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isIdentifierIgnorable(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsISOControl() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isISOControl(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsISOControl() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isISOControl(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsLetter() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isLetter(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsLetter() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isLetter(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsLetterOrDigit() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isLetterOrDigit(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsLetterOrDigit() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isLetterOrDigit(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsLowerCase() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isLowerCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsLowerCase() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isLowerCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsSpaceChar() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isSpaceChar(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsSpaceChar() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isSpaceChar(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsTitleCase() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isTitleCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsTitleCase() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isTitleCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsUnicodeIdentifierPart() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isUnicodeIdentifierPart(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsUnicodeIdentifierPart() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isUnicodeIdentifierPart(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsUnicodeIdentifierStart() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isUnicodeIdentifierStart(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsUnicodeIdentifierStart() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isUnicodeIdentifierStart(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsUpperCase() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + UCharacter.isUpperCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsUpperCase() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isUpperCase(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testIsWhiteSpace() + { + return new PerfTest.Function() { + public void call() { + for (int ch = MIN_; ch < MAX_; ch ++) { + UCharacter.isWhitespace(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + PerfTest.Function testJDKIsWhiteSpace() + { + return new PerfTest.Function() { + public void call() { + for (char ch = (char)MIN_; ch < (char)MAX_; ch ++) { + Character.isWhitespace(ch); + } + } + + public long getOperationsPerIteration() { + return MAX_ - MIN_ + 1; + } + }; + } + + // private data member -------------------------------------------------- + + /** + * Minimum codepoint to do test. Test is ran from MIN_ to MAX_ + */ + private static int MIN_; + /** + * Minimum codepoint to do test. Test is ran from MIN_ to MAX_ + */ + private static int MAX_; +} diff --git a/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UnicodeSetPerf.java b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UnicodeSetPerf.java new file mode 100644 index 000000000..a8e95e1ad --- /dev/null +++ b/icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UnicodeSetPerf.java @@ -0,0 +1,165 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +********************************************************************** +* Copyright (c) 2002-2007, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +package com.ibm.icu.dev.test.perf; +import java.util.HashSet; +import java.util.Iterator; + +import com.ibm.icu.text.UnicodeSet; +import com.ibm.icu.text.UnicodeSetIterator; + +/** + * A class for testing UnicodeSet performance. + * + * @author Alan Liu + * @since ICU 2.4 + */ +public class UnicodeSetPerf extends PerfTest { + + String pattern; + UnicodeSet testChars; + UnicodeSetIterator it; + UnicodeSet us; + HashSet hs; + + public static void main(String[] args) throws Exception { + new UnicodeSetPerf().run(args); + } + + protected void setup(String[] args) { + // We only take one argument, the pattern + if (args.length != 1) { + throw new RuntimeException("Please supply UnicodeSet pattern"); + } + + pattern = args[0]; + testChars = new UnicodeSet(pattern); + it = new UnicodeSetIterator(testChars); + us = new UnicodeSet(); + hs = new HashSet(); + } + + PerfTest.Function testUnicodeSetAdd() { + return new PerfTest.Function() { + public void call() { + us.clear(); + it.reset(); + int n=0; + while (it.nextRange()) { + for (int cp = it.codepoint; cp <= it.codepointEnd; ++cp) { + us.add(cp); + ++n; + } + } + } + + public long getOperationsPerIteration() { + return testChars.size(); + } + }; + } + + PerfTest.Function testHashSetAdd() { + return new PerfTest.Function() { + public void call() { + hs.clear(); + it.reset(); + int n=0; + while (it.nextRange()) { + for (int cp = it.codepoint; cp <= it.codepointEnd; ++cp) { + hs.add(new Integer(cp)); + ++n; + } + } + } + + public long getOperationsPerIteration() { + return testChars.size(); + } + }; + } + + PerfTest.Function testUnicodeSetContains() { + us.clear(); + us.set(testChars); + + return new PerfTest.Function() { + public void call() { + int temp = 0; + for (int cp = 0; cp <= 0x10FFFF; ++cp) { + if (us.contains(cp)) { + temp += cp; + } + } + } + + public long getOperationsPerIteration() { + return 0x110000; + } + }; + } + + PerfTest.Function testHashSetContains() { + hs.clear(); + it.reset(); + while (it.next()) { + hs.add(new Integer(it.codepoint)); + } + return new PerfTest.Function() { + public void call() { + int temp = 0; + for (int cp = 0; cp <= 0x10FFFF; ++cp) { + if (hs.contains(new Integer(cp))) { + temp += cp; + } + } + } + + public long getOperationsPerIteration() { + return 0x110000; + } + }; + } + + PerfTest.Function testUnicodeSetIterate() { + return new PerfTest.Function() { + public void call() { + int temp = 0; + UnicodeSetIterator uit = new UnicodeSetIterator(testChars); + while (uit.next()) { + temp += uit.codepoint; + } + } + + public long getOperationsPerIteration() { + return testChars.size(); + } + }; + } + + PerfTest.Function testHashSetIterate() { + hs.clear(); + it.reset(); + while (it.next()) { + hs.add(new Integer(it.codepoint)); + } + return new PerfTest.Function() { + public void call() { + int temp = 0; + Iterator itr = hs.iterator(); + while (itr.hasNext()) { + temp += ((Integer)itr.next()).intValue(); + } + } + + public long getOperationsPerIteration() { + return testChars.size(); + } + }; + } +} |