]> granicus.if.org Git - icu/commitdiff
ICU-9427 Added perl script for performance test as a part of continuous build
authorDebabrata Sengupta <dsengup@svn.icu-project.org>
Tue, 31 Jul 2012 18:19:15 +0000 (18:19 +0000)
committerDebabrata Sengupta <dsengup@svn.icu-project.org>
Tue, 31 Jul 2012 18:19:15 +0000 (18:19 +0000)
X-SVN-Rev: 32075

.gitattributes
icu4j/perf-tests/data/icuperf2report.xsl [new file with mode: 0644]
icu4j/perf-tests/perftests.pl [new file with mode: 0644]

index 6a9523dec9f51fee0cda925f4105f421b1a3caba..3c1c0dda9316b3e2f6bce670730d785af2fa2562 100644 (file)
@@ -766,6 +766,8 @@ icu4j/main/tests/translit/.settings/org.eclipse.jdt.core.prefs -text
 icu4j/main/tests/translit/.settings/org.eclipse.jdt.ui.prefs -text
 icu4j/main/tests/translit/translit-tests-build.launch -text
 icu4j/manifest.stub -text
+icu4j/perf-tests/data/icuperf2report.xsl -text
+icu4j/perf-tests/perftests.pl -text
 icu4j/samples/build.properties -text
 icu4j/samples/manifest.stub -text
 icu4j/tools/build/.settings/org.eclipse.core.resources.prefs -text
diff --git a/icu4j/perf-tests/data/icuperf2report.xsl b/icu4j/perf-tests/data/icuperf2report.xsl
new file mode 100644 (file)
index 0000000..474f55e
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>\r
+\r
+<!-- Copyright (C) 2012 IBM Corporation and Others. All Rights Reserved. -->\r
+\r
+<xsl:stylesheet version="1.0"\r
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r
+\r
+  <xsl:template match="/perfTestResults">\r
+    <report category="test">\r
+      <!-- For now, include ICU type and version in a comment. -->\r
+      <xsl:comment>\r
+        icu4<xsl:value-of select="@icu"/>-<xsl:value-of select="@version"/>\r
+      </xsl:comment>\r
+\r
+      <xsl:for-each select="perfTestResult">\r
+        <xsl:element name="test">\r
+          <xsl:attribute name="duration">\r
+            <xsl:value-of select="@time"/>\r
+          </xsl:attribute>\r
+          <xsl:attribute name="status">success</xsl:attribute>\r
+          <xsl:attribute name="name">\r
+            <xsl:value-of select="@test"/>\r
+          </xsl:attribute>\r
+          <xsl:attribute name="fixture">\r
+          </xsl:attribute>\r
+          <xsl:attribute name="file">source/test/perf</xsl:attribute>\r
+          <xsl:attribute name="stdout">\r
+            iterations: <xsl:value-of select="@iterations"/>\r
+          </xsl:attribute>\r
+        </xsl:element>\r
+      </xsl:for-each>\r
+    </report>\r
+  </xsl:template>\r
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/icu4j/perf-tests/perftests.pl b/icu4j/perf-tests/perftests.pl
new file mode 100644 (file)
index 0000000..af4f5d6
--- /dev/null
@@ -0,0 +1,447 @@
+#!/usr/local/bin/perl\r
+# *******************************************************************************\r
+# * Copyright (C) 2002-2012 International Business Machines Corporation and     *\r
+# * others. All Rights Reserved.                                                *\r
+# *******************************************************************************\r
+\r
+use XML::LibXML;\r
+\r
+# Assume we are running within the icu4j root directory\r
+use lib 'src/com/ibm/icu/dev/test/perf';\r
+use Dataset;\r
+my $CLASSPATH="../icu4j.jar:../tools/misc/out/lib/icu4j-tools.jar:out/bin";\r
+#---------------------------------------------------------------------\r
+\r
+# Methods to be tested.  Each pair represents a test method and\r
+# a baseline method which is used for comparison.\r
+my @METHODS  = (\r
+                 ['TestJDKConstruction',     'TestICUConstruction'],\r
+                 ['TestJDKParse',            'TestICUParse'],\r
+                 ['TestJDKFormat',           'TestICUFormat']\r
+               );\r
+# Patterns which define the set of characters used for testing.\r
+my @OPTIONS = (\r
+#                 locale    pattern              date string\r
+                [ "en_US",  "dddd MMM yyyy",     "15 Jan 2007"],\r
+                [ "sw_KE",  "dddd MMM yyyy",     "15 Jan 2007"],\r
+                [ "en_US",  "HH:mm",             "13:13"],\r
+                [ "en_US",  "HH:mm zzzz",        "13:13 Pacific Standard Time"],\r
+                [ "en_US",  "HH:mm z",           "13:13 PST"],\r
+                [ "en_US",  "HH:mm Z",           "13:13 -0800"],\r
+              );\r
+\r
+my $THREADS;        # number of threads (input from command-line args)\r
+my $CALIBRATE = 2;  # duration in seconds for initial calibration\r
+my $DURATION  = 10; # duration in seconds for each pass\r
+my $NUMPASSES = 4;  # number of passes.  If > 1 then the first pass\r
+                    # is discarded as a JIT warm-up pass.\r
+\r
+my $TABLEATTR = 'BORDER="1" CELLPADDING="4" CELLSPACING="0"';\r
+\r
+my $PLUS_MINUS = "&plusmn;";\r
+\r
+if ($NUMPASSES < 3) {\r
+    die "Need at least 3 passes.  One is discarded (JIT warmup) and need two to have 1 degree of freedom (t distribution).";\r
+}\r
+\r
+\r
+# run all tests with the specified number of threads from command-line input\r
+# (if there is no arguments, use $THREADS = 1)\r
+foreach my $arg ($#ARGV >= 0 ? @ARGV : "1") {\r
+  $THREADS = $arg;\r
+  main();\r
+}\r
+\r
+\r
+#---------------------------------------------------------------------\r
+sub main {\r
+\r
+#-----------DATE FORMAT PERFORMANCE TESTS-----------------------------\r
+    my $testclass = 'com.ibm.icu.dev.test.perf.DateFormatPerformanceTest';\r
+    #my $threads = ($THREADS > 1) ? "($THREADS threads)" : "";\r
+    \r
+    my $doc = XML::LibXML::Document->new('1.0', 'utf-8');\r
+    my $root = $doc->createElement("perfTestResults");\r
+\r
+ #   my $raw = "";\r
+    my @shortNames = ( "open" , "parse", "fmt");\r
+    my $index=0;\r
+\r
+    for my $methodPair (@METHODS) {\r
+\r
+        my $testMethod = $methodPair->[0];\r
+        my $baselineMethod = $methodPair->[1];\r
+       my $testname = $shortNames[$index];\r
+       $index++;\r
+\r
+        $OUT = '';\r
+       my $patternCounter=1;\r
+\r
+        for my $pat (@OPTIONS) { \r
+\r
+            # measure the test method\r
+            my $t = measure2($testclass, $testMethod, $pat, -$DURATION);\r
+           my $testResult = $t->getMean();\r
+           my $jdkElement = $doc->createElement("perfTestResult");\r
+           my $testName = "DateFmt-$testname-pat$patternCounter-JDK";\r
+           $jdkElement->setAttribute("test" => $testName);\r
+           $jdkElement->setAttribute("iterations" => 1);\r
+           $jdkElement->setAttribute("time" => $testResult);\r
+           $root->appendChild($jdkElement);\r
+\r
+            # measure baseline method\r
+            my $b = measure2($testclass, $baselineMethod, $pat, -$DURATION);\r
+            my $baseResult = $b->getMean();\r
+           my $icuElement = $doc->createElement("perfTestResult");\r
+           my $testName = "DateFmt-$testname-pat$patternCounter";\r
+           $patternCounter++;\r
+           $icuElement->setAttribute("test"=> $testName);\r
+           $icuElement->setAttribute("iterations" => 1); \r
+           $icuElement->setAttribute("time" => $baseResult);\r
+           $root->appendChild($icuElement);\r
+\r
+       }\r
+    }\r
+\r
+#------------------DECIMAL FORMAT TESTS---------------------------------\r
+\r
+    my $testclass = 'com.ibm.icu.dev.test.perf.DecimalFormatPerformanceTest';\r
+    my @OPTIONS = (\r
+#              locale      pattern     date string\r
+               [ "en_US", "#,###.##", "1,234.56"],\r
+               [ "de_DE", "#,###.##", "1.234,56"],\r
+               );\r
+    my $index=0;\r
+    for my $methodPair (@METHODS) {\r
+\r
+        my $testMethod = $methodPair->[0];\r
+        my $baselineMethod = $methodPair->[1];\r
+       my $testname = $shortNames[$index];\r
+       $index++;\r
+       \r
+\r
+        for my $pat (@OPTIONS) {\r
+           my $pat0 = $pat->[0];\r
+           my $patternName = $pat0->[0]; \r
+\r
+            # measure the test method\r
+            my $t = measure2($testclass, $testMethod, $pat, -$DURATION);\r
+           my $testResult = $t->getMean();\r
+           my $jdkElement = $doc->createElement("perfTestResult");\r
+           my $testName = "NumFmt-$testname-$patternName-JDK";\r
+           $jdkElement->setAttribute("test" => $testName);\r
+           $jdkElement->setAttribute("iterations"=>1);\r
+           $jdkElement->setAttribute("time" => $testResult);\r
+           $root->appendChild($jdkElement);\r
+\r
+            # measure baseline method\r
+            my $b = measure2($testclass, $baselineMethod, $pat, -$DURATION);\r
+            my $baseResult = $b->getMean();\r
+           my $icuElement = $doc->createElement("perfTestResult");\r
+           my $testName = "NumFmt-$testname-$patternName";\r
+           $icuElement->setAttribute("test"=> $testName);\r
+           $icuElement->setAttribute("iterations"=>1);\r
+           $icuElement->setAttribute("time" => $baseResult);\r
+           $root->appendChild($icuElement);\r
+       }\r
+    }\r
+\r
+#----------------COLLATION PERFORMANCE TESTS--------------------------_\r
+\r
+    %dataFiles = (\r
+          "en_US",         "TestNames_Latin.txt",\r
+          "da_DK",         "TestNames_Latin.txt",\r
+          "de_DE",         "TestNames_Latin.txt",\r
+          "de__PHONEBOOK", "TestNames_Latin.txt",\r
+          "fr_FR",         "TestNames_Latin.txt",\r
+          "ja_JP",         "TestNames_Latin.txt TestNames_Japanese_h.txt TestNames_Japanese_k.txt TestNames_Asian.txt",\r
+          "zh_CN",         "TestNames_Latin.txt TestNames_Chinese.txt",\r
+          "zh_TW",         "TestNames_Latin.txt TestNames_Chinese.txt",\r
+          "zh__PINYIN",    "TestNames_Latin.txt TestNames_Chinese.txt",\r
+          "ru_RU",         "TestNames_Latin.txt TestNames_Russian.txt",\r
+          "th",            "TestNames_Latin.txt TestNames_Thai.txt",\r
+          "ko_KR",         "TestNames_Latin.txt TestNames_Korean.txt",\r
+          );\r
+       \r
+    #  Outer loop runs through the locales to test\r
+    #     (Edit this list dirctly to make changes)\r
+    #\r
+    foreach  $locale (\r
+          "en_US",\r
+          "da_DK",\r
+          "de_DE",\r
+          "de__PHONEBOOK",\r
+          "fr_FR",\r
+          "ja_JP",\r
+           "zh_CN",\r
+          "zh_TW",\r
+          "zh__PINYIN",\r
+           "ko_KR",\r
+          "ru_RU",\r
+          "th",\r
+                   )\r
+       {\r
+       \r
+       \r
+       #\r
+       # Inner loop runs over the set of data files specified for each locale.\r
+       #    (Edit the %datafiles initialization, above, to make changes.\r
+       #\r
+        $ff = $dataFiles{$locale};\r
+        @ff = split(/[\s]+/, $ff);\r
+        $counter = 1;\r
+        foreach  $data (@ff) {\r
+          #\r
+          # Run ICU Test for this (locale, data file) pair.\r
+          #\r
+           $iStrCol = `java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file src/com/ibm/icu/dev/test/perf/data/collation/$data -locale $locale -loop 1000 -binsearch`;\r
+print "java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file src/com/ibm/icu/dev/test/perf/data/collation/$data -locale $locale -loop 1000 -binsearch\n";\r
+  $iStrCol =~s/[,\s]*//g;  # whack off the leading "  ," in the returned result.\r
+          doKeyTimes("java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file src/com/ibm/icu/dev/test/perf/data/collation/$data -locale $locale -loop 1000 -keygen",\r
+                    my $iKeyGen, my $iKeyLen);\r
+\r
+          #\r
+          # Run Windows test for this (locale, data file) pair.  Only do if\r
+          #    we are not on Windows 98/ME and we hava a windows langID\r
+          #    for the locale.\r
+          #\r
+           $wStrCol =  $wKeyGen =  $wKeyLen = 0;\r
+          my $wStrCol = `java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file src/com/ibm/icu/dev/test/perf/data/collation/$data -locale $locale -loop 1000 -binsearch -java`;\r
+          $wStrCol =~s/[,\s]*//g;  # whack off the leading "  ," in the returned result.\r
+          doKeyTimes("java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file src/com/ibm/icu/dev/test/perf/data/collation/$data -locale $locale -loop 1000 -keygen -java",\r
+                     $wKeyGen, $wKeyLen);\r
+                     \r
+           $collDiff =  $keyGenDiff =  $keyLenDiff = 0;\r
+          if ($wKeyLen > 0) {\r
+               $collDiff   = (($wStrCol - $iStrCol) / $iStrCol) * 100;\r
+               $keyGenDiff = (($wKeyGen - $iKeyGen) / $iKeyGen) * 100;\r
+               $keyLenDiff = (($wKeyLen - $iKeyLen) / $iKeyLen) * 100;\r
+          }\r
+\r
+       my $ICU = $doc->createElement("perfTestResult");\r
+       my $testname = "Coll-$locale-data$counter-StrCol";\r
+       #write the results corresponding to this local,data pair\r
+       $ICU->setAttribute("test"=> $testname);\r
+       $ICU->setAttribute("iterations"=>1000);\r
+       $ICU->setAttribute("time"=> $iStrCol);\r
+       $root->appendChild($ICU);\r
+\r
+       my $Key = $doc->createElement("perfTestResult");\r
+       my $testname = "Coll-$locale-data$counter-keyGen";\r
+       $Key->setAttribute("test"=> $testname);\r
+       $Key->setAttribute("iterations"=>1000);\r
+       $Key->setAttribute("time"=>$iKeyGen);\r
+       $root->appendChild($Key);\r
+\r
+       my $JDK = $doc->createElement("perfTestResult");\r
+       my $testname = "Coll-$locale-data$counter-StrCol-JDK";\r
+       $JDK->setAttribute("test"=>$testname);\r
+       $JDK->setAttribute("iterations"=>1000);\r
+       $JDK->setAttribute("time"=>$wStrCol);\r
+       $root->appendChild($JDK);\r
+\r
+       my $Key = $doc->createElement("perfTestResult");\r
+       my $testname = "Coll-$locale-data$counter-keyGen-JDK";\r
+       $Key->setAttribute("test"=>$testname);\r
+       $Key->setAttribute("iterations"=>1000);\r
+       $Key->setAttribute("time"=>$wKeyGen);\r
+       $root->appendChild($Key);\r
+       $counter++;\r
+     }\r
+   }\r
+\r
+\r
+\r
+#----------WRITE RESULTS TO perf.xml-----------------------\r
+    $doc->setDocumentElement($root);\r
+    open my $out_fh, '>', "perf.xml";\r
+    print {$out_fh} $doc->toString;\r
+}\r
+\r
+\r
+#---------------------------------------------------------------------\r
+# Append text to the global variable $OUT\r
+sub out {\r
+   $OUT .= join('', @_);\r
+}\r
+\r
+\r
+#---------------------------------------------------------------------\r
+# Measure a given test method with a give test pattern using the\r
+# global run parameters.\r
+#\r
+# @param the method to run\r
+# @param the pattern defining characters to test\r
+# @param if >0 then the number of iterations per pass.  If <0 then\r
+#        (negative of) the number of seconds per pass.\r
+#\r
+# @return a Dataset object, scaled by iterations per pass and\r
+#         events per iteration, to give time per event\r
+#\r
+sub measure2 {\r
+    my @data = measure1(@_);\r
+    my $iterPerPass = shift(@data);\r
+    my $eventPerIter = shift(@data);\r
+\r
+    shift(@data) if (@data > 1); # discard first run\r
+\r
+    my $ds = Dataset->new(@data);\r
+    $ds->setScale(1.0e-3 / ($iterPerPass * $eventPerIter));\r
+    $ds;\r
+}\r
+\r
+#---------------------------------------------------------------------\r
+# Measure a given test method with a give test pattern using the\r
+# global run parameters.\r
+#\r
+# @param the method to run\r
+# @param the pattern defining characters to test\r
+# @param if >0 then the number of iterations per pass.  If <0 then\r
+#        (negative of) the number of seconds per pass.\r
+#\r
+# @return array of:\r
+#         [0] iterations per pass\r
+#         [1] events per iteration\r
+#         [2..] ms reported for each pass, in order\r
+#\r
+sub measure1 {\r
+    my $testclass = shift;\r
+    my $method = shift;\r
+    my $pat = shift;\r
+    my $iterCount = shift; # actually might be -seconds/pass\r
+\r
+    # is $iterCount actually -seconds/pass?\r
+    if ($iterCount < 0) {\r
+\r
+        # calibrate: estimate ms/iteration\r
+        print "Calibrating...";\r
+        my @t = callJava($testclass, $method, $pat, -$CALIBRATE, 1);\r
+        print "done.\n";\r
+\r
+        my @data = split(/\s+/, $t[0]->[2]);\r
+        $data[0] *= 1.0e+3;\r
+\r
+        my $timePerIter = 1.0e-3 * $data[0] / $data[1];\r
+        \r
+        # determine iterations/pass\r
+        $iterCount = int(-$iterCount / $timePerIter + 0.5);\r
+   }\r
+    \r
+    # run passes\r
+    print "Measuring $iterCount iterations x $NUMPASSES passes...";\r
+    my @t = callJava($testclass, $method, $pat, $iterCount, $NUMPASSES);\r
+    print "done.\n";\r
+    my @ms = ();\r
+    my @b; # scratch\r
+    for my $a (@t) {\r
+        # $a->[0]: method name, corresponds to $method\r
+        # $a->[1]: 'begin' data, == $iterCount\r
+        # $a->[2]: 'end' data, of the form <ms> <loops> <eventsPerIter>\r
+        # $a->[3...]: gc messages from JVM during pass\r
+        @b = split(/\s+/, $a->[2]);\r
+        push(@ms, $b[0] * 1.0e+3);\r
+    }\r
+    my $eventsPerIter = $b[2];\r
+\r
+    my @ms_str = @ms;\r
+    $ms_str[0] .= " (discarded)" if (@ms_str > 1);\r
+\r
+    ($iterCount, $eventsPerIter, @ms);\r
+}\r
+\r
+#---------------------------------------------------------------------\r
+# Invoke java to run $TESTCLASS, passing it the given parameters.\r
+#\r
+# @param the method to run\r
+# @param the number of iterations, or if negative, the duration\r
+#        in seconds.  If more than on pass is desired, pass in\r
+#        a string, e.g., "100 100 100".\r
+# @param the pattern defining characters to test\r
+#\r
+# @return an array of results.  Each result is an array REF\r
+#         describing one pass.  The array REF contains:\r
+#         ->[0]: The method name as reported\r
+#         ->[1]: The params on the '= <meth> begin ...' line\r
+#         ->[2]: The params on the '= <meth> end ...' line\r
+#         ->[3..]: GC messages from the JVM, if any\r
+#\r
+sub callJava {\r
+    my $testclass = shift;\r
+    my $method = shift;\r
+    my $pat = shift;\r
+    my $n = shift;\r
+    my $passes = shift;\r
+    \r
+    my $n = ($n < 0) ? "-t ".(-$n) : "-i ".$n;\r
+    \r
+    my $cmd = "java -classpath $CLASSPATH $testclass $method $n -p $passes -L @$pat[0] \"@$pat[1]\" \"@$pat[2]\" -r $THREADS";\r
+    print "[$cmd]\n"; # for debugging\r
+    open(PIPE, "$cmd|") or die "Can't run \"$cmd\"";\r
+    my @out;\r
+    while (<PIPE>) {\r
+        push(@out, $_);\r
+    }\r
+    close(PIPE) or die "Java failed: \"$cmd\"";\r
+\r
+    @out = grep(!/^\#/, @out);  # filter out comments\r
+\r
+    #print "[", join("\n", @out), "]\n";\r
+\r
+    my @results;\r
+    my $method = '';\r
+    my $data = [];\r
+    foreach (@out) {\r
+        next unless (/\S/);\r
+\r
+        if (/^=\s*(\w+)\s*(\w+)\s*(.*)/) {\r
+            my ($m, $state, $d) = ($1, $2, $3);\r
+            #print "$_ => [[$m $state $data]]\n";\r
+            if ($state eq 'begin') {\r
+                die "$method was begun but not finished" if ($method);\r
+                $method = $m;\r
+                push(@$data, $d);\r
+                push(@$data, ''); # placeholder for end data\r
+            } elsif ($state eq 'end') {\r
+                if ($m ne $method) {\r
+                    die "$method end does not match: $_";\r
+                }\r
+                $data->[1] = $d; # insert end data at [1]\r
+                #print "#$method:", join(";",@$data), "\n";\r
+                unshift(@$data, $method); # add method to start\r
+\r
+                push(@results, $data);\r
+                $method = '';\r
+                $data = [];\r
+            } else {\r
+                die "Can't parse: $_";\r
+           }\r
+        }\r
+       elsif (/^\[/) {\r
+            if ($method) {\r
+                push(@$data, $_);\r
+            } else {\r
+                # ignore extraneous GC notices\r
+            }\r
+        }\r
+        else {\r
+            die "Can't parse: $_";\r
+        }\r
+    }\r
+\r
+    die "$method was begun but not finished" if ($method);\r
+\r
+    @results;\r
+}\r
+\r
+#-----------------------------------------------------------------------------------\r
+#  doKeyGenTimes($Command_to_run, $time, $key_length)\r
+#       Do a key-generation test and return the time and key length/char values.\r
+#\r
+sub doKeyTimes($$$) {\r
+   # print "$_[0]\n";\r
+   local($x) = `$_[0]`;                  # execute the collperf command.\r
+   ($_[1], $_[2]) = split(/\,/, $x);     # collperf returns "time, keylength" string.\r
+}\r
+\r
+\r
+#eof\r