summaryrefslogtreecommitdiff
path: root/icu4j/perf-tests/src/main/java/com
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-28 17:54:57 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-28 17:54:57 +0000
commiteb3451793aaf42870e44281708ccac51c010e837 (patch)
tree51c5f3646653b5153a74a2828b2af20c41cbd8d1 /icu4j/perf-tests/src/main/java/com
parente710c4fbd23e1b7d97da0a88a8499326861ad250 (diff)
parent8144ba71b4efcfe46cd0e76e85d371bcc7d55567 (diff)
downloadicu-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')
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/BreakIteratorPerformanceTest.java196
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/CollationPerformanceTest.java1273
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ConverterPerformanceTest.java320
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DateFormatPerformanceTest.java117
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/DecimalFormatPerformanceTest.java121
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/NormalizerPerformanceTest.java704
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/PerfTest.java961
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/RBBIPerf.java161
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ResourceBundlePerf.java374
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/ServiceObjectCreationPerf.java82
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UCharacterPerf.java535
-rw-r--r--icu4j/perf-tests/src/main/java/com/ibm/icu/dev/test/perf/UnicodeSetPerf.java165
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();
+ }
+ };
+ }
+}