xref: /aosp_15_r20/external/icu/icu4j/perf-tests/perftests.pl (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker#!/usr/local/bin/perl
2*0e209d39SAndroid Build Coastguard Worker# * © 2016 and later: Unicode, Inc. and others.
3*0e209d39SAndroid Build Coastguard Worker# * License & terms of use: http://www.unicode.org/copyright.html
4*0e209d39SAndroid Build Coastguard Worker# *******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker# * Copyright (C) 2002-2012 International Business Machines Corporation and     *
6*0e209d39SAndroid Build Coastguard Worker# * others. All Rights Reserved.                                                *
7*0e209d39SAndroid Build Coastguard Worker# *******************************************************************************
8*0e209d39SAndroid Build Coastguard Worker
9*0e209d39SAndroid Build Coastguard Workeruse XML::LibXML;
10*0e209d39SAndroid Build Coastguard Worker
11*0e209d39SAndroid Build Coastguard Worker# Assume we are running within the icu4j root directory
12*0e209d39SAndroid Build Coastguard Workeruse lib '.';
13*0e209d39SAndroid Build Coastguard Workeruse Dataset;
14*0e209d39SAndroid Build Coastguard Workermy $OS=$^O;
15*0e209d39SAndroid Build Coastguard Worker
16*0e209d39SAndroid Build Coastguard Workermy $CLASSPATH;
17*0e209d39SAndroid Build Coastguard Workerif ($OS eq "linux" || $OS eq "darwin") {
18*0e209d39SAndroid Build Coastguard Worker	$CLASSPATH="../icu4j.jar:../tools/misc/out/lib/icu4j-tools.jar:out/bin";
19*0e209d39SAndroid Build Coastguard Worker} else {
20*0e209d39SAndroid Build Coastguard Worker	$CLASSPATH="../icu4j.jar;../tools/misc/out/lib/icu4j-tools.jar;out/bin";
21*0e209d39SAndroid Build Coastguard Worker}
22*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
23*0e209d39SAndroid Build Coastguard Worker
24*0e209d39SAndroid Build Coastguard Worker# Methods to be tested.  Each pair represents a test method and
25*0e209d39SAndroid Build Coastguard Worker# a baseline method which is used for comparison.
26*0e209d39SAndroid Build Coastguard Workermy @METHODS  = (
27*0e209d39SAndroid Build Coastguard Worker                 ['TestJDKConstruction',     'TestICUConstruction'],
28*0e209d39SAndroid Build Coastguard Worker                 ['TestJDKParse',            'TestICUParse'],
29*0e209d39SAndroid Build Coastguard Worker                 ['TestJDKFormat',           'TestICUFormat']
30*0e209d39SAndroid Build Coastguard Worker               );
31*0e209d39SAndroid Build Coastguard Worker# Patterns which define the set of characters used for testing.
32*0e209d39SAndroid Build Coastguard Workermy @OPTIONS = (
33*0e209d39SAndroid Build Coastguard Worker#                 locale    pattern              date string
34*0e209d39SAndroid Build Coastguard Worker                [ "en_US",  "dddd MMM yyyy",     "15 Jan 2007"],
35*0e209d39SAndroid Build Coastguard Worker                [ "sw_KE",  "dddd MMM yyyy",     "15 Jan 2007"],
36*0e209d39SAndroid Build Coastguard Worker                [ "en_US",  "HH:mm",             "13:13"],
37*0e209d39SAndroid Build Coastguard Worker                [ "en_US",  "HH:mm zzzz",        "13:13 Pacific Standard Time"],
38*0e209d39SAndroid Build Coastguard Worker                [ "en_US",  "HH:mm z",           "13:13 PST"],
39*0e209d39SAndroid Build Coastguard Worker                [ "en_US",  "HH:mm Z",           "13:13 -0800"],
40*0e209d39SAndroid Build Coastguard Worker              );
41*0e209d39SAndroid Build Coastguard Worker
42*0e209d39SAndroid Build Coastguard Workermy $THREADS;        # number of threads (input from command-line args)
43*0e209d39SAndroid Build Coastguard Workermy $CALIBRATE = 2;  # duration in seconds for initial calibration
44*0e209d39SAndroid Build Coastguard Workermy $DURATION  = 10; # duration in seconds for each pass
45*0e209d39SAndroid Build Coastguard Workermy $NUMPASSES = 4;  # number of passes.  If > 1 then the first pass
46*0e209d39SAndroid Build Coastguard Worker                    # is discarded as a JIT warm-up pass.
47*0e209d39SAndroid Build Coastguard Worker
48*0e209d39SAndroid Build Coastguard Workermy $TABLEATTR = 'BORDER="1" CELLPADDING="4" CELLSPACING="0"';
49*0e209d39SAndroid Build Coastguard Worker
50*0e209d39SAndroid Build Coastguard Workermy $PLUS_MINUS = "±";
51*0e209d39SAndroid Build Coastguard Worker
52*0e209d39SAndroid Build Coastguard Workerif ($NUMPASSES < 3) {
53*0e209d39SAndroid Build Coastguard Worker    die "Need at least 3 passes.  One is discarded (JIT warmup) and need two to have 1 degree of freedom (t distribution).";
54*0e209d39SAndroid Build Coastguard Worker}
55*0e209d39SAndroid Build Coastguard Worker
56*0e209d39SAndroid Build Coastguard Worker
57*0e209d39SAndroid Build Coastguard Worker# run all tests with the specified number of threads from command-line input
58*0e209d39SAndroid Build Coastguard Worker# (if there is no arguments, use $THREADS = 1)
59*0e209d39SAndroid Build Coastguard Workerforeach my $arg ($#ARGV >= 0 ? @ARGV : "1") {
60*0e209d39SAndroid Build Coastguard Worker  $THREADS = $arg;
61*0e209d39SAndroid Build Coastguard Worker  main();
62*0e209d39SAndroid Build Coastguard Worker}
63*0e209d39SAndroid Build Coastguard Worker
64*0e209d39SAndroid Build Coastguard Worker
65*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
66*0e209d39SAndroid Build Coastguard Workersub main {
67*0e209d39SAndroid Build Coastguard Worker
68*0e209d39SAndroid Build Coastguard Worker#-----------DATE FORMAT PERFORMANCE TESTS-----------------------------
69*0e209d39SAndroid Build Coastguard Worker    my $testclass = 'com.ibm.icu.dev.test.perf.DateFormatPerformanceTest';
70*0e209d39SAndroid Build Coastguard Worker    #my $threads = ($THREADS > 1) ? "($THREADS threads)" : "";
71*0e209d39SAndroid Build Coastguard Worker
72*0e209d39SAndroid Build Coastguard Worker    my $doc = XML::LibXML::Document->new('1.0', 'utf-8');
73*0e209d39SAndroid Build Coastguard Worker    my $root = $doc->createElement("perfTestResults");
74*0e209d39SAndroid Build Coastguard Worker
75*0e209d39SAndroid Build Coastguard Worker #   my $raw = "";
76*0e209d39SAndroid Build Coastguard Worker    my @shortNames = ( "open" , "parse", "fmt");
77*0e209d39SAndroid Build Coastguard Worker    my $index=0;
78*0e209d39SAndroid Build Coastguard Worker
79*0e209d39SAndroid Build Coastguard Worker    for my $methodPair (@METHODS) {
80*0e209d39SAndroid Build Coastguard Worker
81*0e209d39SAndroid Build Coastguard Worker        my $testMethod = $methodPair->[0];
82*0e209d39SAndroid Build Coastguard Worker        my $baselineMethod = $methodPair->[1];
83*0e209d39SAndroid Build Coastguard Worker	my $testname = $shortNames[$index];
84*0e209d39SAndroid Build Coastguard Worker	$index++;
85*0e209d39SAndroid Build Coastguard Worker
86*0e209d39SAndroid Build Coastguard Worker        $OUT = '';
87*0e209d39SAndroid Build Coastguard Worker	my $patternCounter=1;
88*0e209d39SAndroid Build Coastguard Worker
89*0e209d39SAndroid Build Coastguard Worker        for my $pat (@OPTIONS) {
90*0e209d39SAndroid Build Coastguard Worker
91*0e209d39SAndroid Build Coastguard Worker            # measure the test method
92*0e209d39SAndroid Build Coastguard Worker            my $t = measure2($testclass, $testMethod, $pat, -$DURATION);
93*0e209d39SAndroid Build Coastguard Worker	    my $testResult = $t->getMean();
94*0e209d39SAndroid Build Coastguard Worker	    my $jdkElement = $doc->createElement("perfTestResult");
95*0e209d39SAndroid Build Coastguard Worker	    my $testName = "DateFmt-$testname-pat$patternCounter-JDK";
96*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("test" => $testName);
97*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("iterations" => 1);
98*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("time" => $testResult);
99*0e209d39SAndroid Build Coastguard Worker	    $root->appendChild($jdkElement);
100*0e209d39SAndroid Build Coastguard Worker
101*0e209d39SAndroid Build Coastguard Worker            # measure baseline method
102*0e209d39SAndroid Build Coastguard Worker            my $b = measure2($testclass, $baselineMethod, $pat, -$DURATION);
103*0e209d39SAndroid Build Coastguard Worker            my $baseResult = $b->getMean();
104*0e209d39SAndroid Build Coastguard Worker	    my $icuElement = $doc->createElement("perfTestResult");
105*0e209d39SAndroid Build Coastguard Worker	    my $testName = "DateFmt-$testname-pat$patternCounter";
106*0e209d39SAndroid Build Coastguard Worker	    $patternCounter++;
107*0e209d39SAndroid Build Coastguard Worker	    $icuElement->setAttribute("test"=> $testName);
108*0e209d39SAndroid Build Coastguard Worker 	    $icuElement->setAttribute("iterations" => 1);
109*0e209d39SAndroid Build Coastguard Worker	    $icuElement->setAttribute("time" => $baseResult);
110*0e209d39SAndroid Build Coastguard Worker	    $root->appendChild($icuElement);
111*0e209d39SAndroid Build Coastguard Worker
112*0e209d39SAndroid Build Coastguard Worker       }
113*0e209d39SAndroid Build Coastguard Worker    }
114*0e209d39SAndroid Build Coastguard Worker
115*0e209d39SAndroid Build Coastguard Worker#------------------DECIMAL FORMAT TESTS---------------------------------
116*0e209d39SAndroid Build Coastguard Worker
117*0e209d39SAndroid Build Coastguard Worker    my $testclass = 'com.ibm.icu.dev.test.perf.DecimalFormatPerformanceTest';
118*0e209d39SAndroid Build Coastguard Worker    my @OPTIONS = (
119*0e209d39SAndroid Build Coastguard Worker#		locale	    pattern	date string
120*0e209d39SAndroid Build Coastguard Worker		[ "en_US", "#,###.##", "1,234.56"],
121*0e209d39SAndroid Build Coastguard Worker		[ "de_DE", "#,###.##", "1.234,56"],
122*0e209d39SAndroid Build Coastguard Worker		);
123*0e209d39SAndroid Build Coastguard Worker    my $index=0;
124*0e209d39SAndroid Build Coastguard Worker    for my $methodPair (@METHODS) {
125*0e209d39SAndroid Build Coastguard Worker
126*0e209d39SAndroid Build Coastguard Worker        my $testMethod = $methodPair->[0];
127*0e209d39SAndroid Build Coastguard Worker        my $baselineMethod = $methodPair->[1];
128*0e209d39SAndroid Build Coastguard Worker	my $testname = $shortNames[$index];
129*0e209d39SAndroid Build Coastguard Worker	$index++;
130*0e209d39SAndroid Build Coastguard Worker
131*0e209d39SAndroid Build Coastguard Worker
132*0e209d39SAndroid Build Coastguard Worker        for my $pat (@OPTIONS) {
133*0e209d39SAndroid Build Coastguard Worker	       my $patternName = $pat->[0];
134*0e209d39SAndroid Build Coastguard Worker
135*0e209d39SAndroid Build Coastguard Worker            # measure the test method
136*0e209d39SAndroid Build Coastguard Worker            my $t = measure2($testclass, $testMethod, $pat, -$DURATION);
137*0e209d39SAndroid Build Coastguard Worker	    my $testResult = $t->getMean();
138*0e209d39SAndroid Build Coastguard Worker	    my $jdkElement = $doc->createElement("perfTestResult");
139*0e209d39SAndroid Build Coastguard Worker	    my $testName = "NumFmt-$testname-$patternName-JDK";
140*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("test" => $testName);
141*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("iterations"=>1);
142*0e209d39SAndroid Build Coastguard Worker	    $jdkElement->setAttribute("time" => $testResult);
143*0e209d39SAndroid Build Coastguard Worker	    $root->appendChild($jdkElement);
144*0e209d39SAndroid Build Coastguard Worker
145*0e209d39SAndroid Build Coastguard Worker            # measure baseline method
146*0e209d39SAndroid Build Coastguard Worker            my $b = measure2($testclass, $baselineMethod, $pat, -$DURATION);
147*0e209d39SAndroid Build Coastguard Worker            my $baseResult = $b->getMean();
148*0e209d39SAndroid Build Coastguard Worker	    my $icuElement = $doc->createElement("perfTestResult");
149*0e209d39SAndroid Build Coastguard Worker	    my $testName = "NumFmt-$testname-$patternName";
150*0e209d39SAndroid Build Coastguard Worker	    $icuElement->setAttribute("test"=> $testName);
151*0e209d39SAndroid Build Coastguard Worker	    $icuElement->setAttribute("iterations"=>1);
152*0e209d39SAndroid Build Coastguard Worker	    $icuElement->setAttribute("time" => $baseResult);
153*0e209d39SAndroid Build Coastguard Worker	    $root->appendChild($icuElement);
154*0e209d39SAndroid Build Coastguard Worker	}
155*0e209d39SAndroid Build Coastguard Worker    }
156*0e209d39SAndroid Build Coastguard Worker
157*0e209d39SAndroid Build Coastguard Worker#----------------COLLATION PERFORMANCE TESTS--------------------------_
158*0e209d39SAndroid Build Coastguard Worker
159*0e209d39SAndroid Build Coastguard Worker    %dataFiles = (
160*0e209d39SAndroid Build Coastguard Worker   	   "en_US",         "TestNames_Latin.txt",
161*0e209d39SAndroid Build Coastguard Worker	   "da_DK",         "TestNames_Latin.txt",
162*0e209d39SAndroid Build Coastguard Worker	   "de_DE",         "TestNames_Latin.txt",
163*0e209d39SAndroid Build Coastguard Worker	   "de__PHONEBOOK", "TestNames_Latin.txt",
164*0e209d39SAndroid Build Coastguard Worker	   "fr_FR",         "TestNames_Latin.txt",
165*0e209d39SAndroid Build Coastguard Worker	   "ja_JP",         "TestNames_Latin.txt TestNames_Japanese_h.txt TestNames_Japanese_k.txt TestNames_Asian.txt",
166*0e209d39SAndroid Build Coastguard Worker	   "zh_CN",         "TestNames_Latin.txt TestNames_Chinese.txt",
167*0e209d39SAndroid Build Coastguard Worker	   "zh_TW",         "TestNames_Latin.txt TestNames_Chinese.txt",
168*0e209d39SAndroid Build Coastguard Worker	   "zh__PINYIN",    "TestNames_Latin.txt TestNames_Chinese.txt",
169*0e209d39SAndroid Build Coastguard Worker	   "ru_RU", 	    "TestNames_Latin.txt TestNames_Russian.txt",
170*0e209d39SAndroid Build Coastguard Worker	   "th",            "TestNames_Latin.txt TestNames_Thai.txt",
171*0e209d39SAndroid Build Coastguard Worker	   "ko_KR",         "TestNames_Latin.txt TestNames_Korean.txt",
172*0e209d39SAndroid Build Coastguard Worker	   );
173*0e209d39SAndroid Build Coastguard Worker
174*0e209d39SAndroid Build Coastguard Worker    #  Outer loop runs through the locales to test
175*0e209d39SAndroid Build Coastguard Worker    #     (Edit this list directly to make changes)
176*0e209d39SAndroid Build Coastguard Worker    #
177*0e209d39SAndroid Build Coastguard Worker    foreach  $locale (
178*0e209d39SAndroid Build Coastguard Worker	   "en_US",
179*0e209d39SAndroid Build Coastguard Worker	   "da_DK",
180*0e209d39SAndroid Build Coastguard Worker	   "de_DE",
181*0e209d39SAndroid Build Coastguard Worker	   "de__PHONEBOOK",
182*0e209d39SAndroid Build Coastguard Worker	   "fr_FR",
183*0e209d39SAndroid Build Coastguard Worker	   "ja_JP",
184*0e209d39SAndroid Build Coastguard Worker           "zh_CN",
185*0e209d39SAndroid Build Coastguard Worker	   "zh_TW",
186*0e209d39SAndroid Build Coastguard Worker	   "zh__PINYIN",
187*0e209d39SAndroid Build Coastguard Worker           "ko_KR",
188*0e209d39SAndroid Build Coastguard Worker	   "ru_RU",
189*0e209d39SAndroid Build Coastguard Worker	   "th",
190*0e209d39SAndroid Build Coastguard Worker                   )
191*0e209d39SAndroid Build Coastguard Worker       {
192*0e209d39SAndroid Build Coastguard Worker
193*0e209d39SAndroid Build Coastguard Worker
194*0e209d39SAndroid Build Coastguard Worker       #
195*0e209d39SAndroid Build Coastguard Worker       # Inner loop runs over the set of data files specified for each locale.
196*0e209d39SAndroid Build Coastguard Worker       #    (Edit the %datafiles initialization, above, to make changes.
197*0e209d39SAndroid Build Coastguard Worker       #
198*0e209d39SAndroid Build Coastguard Worker        $ff = $dataFiles{$locale};
199*0e209d39SAndroid Build Coastguard Worker        @ff = split(/[\s]+/, $ff);
200*0e209d39SAndroid Build Coastguard Worker        $counter = 1;
201*0e209d39SAndroid Build Coastguard Worker        foreach  $data (@ff) {
202*0e209d39SAndroid Build Coastguard Worker          #
203*0e209d39SAndroid Build Coastguard Worker          # Run ICU Test for this (locale, data file) pair.
204*0e209d39SAndroid Build Coastguard Worker          #
205*0e209d39SAndroid Build Coastguard Worker           $iStrCol = `java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file data/collation/$data -locale $locale -loop 1000 -binsearch`;
206*0e209d39SAndroid Build Coastguard Workerprint "java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file data/collation/$data -locale $locale -loop 1000 -binsearch\n";
207*0e209d39SAndroid Build Coastguard Worker  $iStrCol =~s/[,\s]*//g;  # whack off the leading "  ," in the returned result.
208*0e209d39SAndroid Build Coastguard Worker          doKeyTimes("java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file data/collation/$data -locale $locale -loop 1000 -keygen",
209*0e209d39SAndroid Build Coastguard Worker                    my $iKeyGen, my $iKeyLen);
210*0e209d39SAndroid Build Coastguard Worker
211*0e209d39SAndroid Build Coastguard Worker          #
212*0e209d39SAndroid Build Coastguard Worker          # Run Windows test for this (locale, data file) pair.  Only do if
213*0e209d39SAndroid Build Coastguard Worker          #    we are not on Windows 98/ME and we hava a windows langID
214*0e209d39SAndroid Build Coastguard Worker          #    for the locale.
215*0e209d39SAndroid Build Coastguard Worker          #
216*0e209d39SAndroid Build Coastguard Worker           $wStrCol =  $wKeyGen =  $wKeyLen = 0;
217*0e209d39SAndroid Build Coastguard Worker          my $wStrCol = `java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file data/collation/$data -locale $locale -loop 1000 -binsearch -java`;
218*0e209d39SAndroid Build Coastguard Worker          $wStrCol =~s/[,\s]*//g;  # whack off the leading "  ," in the returned result.
219*0e209d39SAndroid Build Coastguard Worker          doKeyTimes("java -classpath $CLASSPATH com.ibm.icu.dev.test.perf.CollationPerformanceTest -terse -file data/collation/$data -locale $locale -loop 1000 -keygen -java",
220*0e209d39SAndroid Build Coastguard Worker                     $wKeyGen, $wKeyLen);
221*0e209d39SAndroid Build Coastguard Worker
222*0e209d39SAndroid Build Coastguard Worker           $collDiff =  $keyGenDiff =  $keyLenDiff = 0;
223*0e209d39SAndroid Build Coastguard Worker          if ($wKeyLen > 0) {
224*0e209d39SAndroid Build Coastguard Worker               $collDiff   = (($wStrCol - $iStrCol) / $iStrCol) * 100;
225*0e209d39SAndroid Build Coastguard Worker               $keyGenDiff = (($wKeyGen - $iKeyGen) / $iKeyGen) * 100;
226*0e209d39SAndroid Build Coastguard Worker               $keyLenDiff = (($wKeyLen - $iKeyLen) / $iKeyLen) * 100;
227*0e209d39SAndroid Build Coastguard Worker          }
228*0e209d39SAndroid Build Coastguard Worker
229*0e209d39SAndroid Build Coastguard Worker	my $ICU = $doc->createElement("perfTestResult");
230*0e209d39SAndroid Build Coastguard Worker	my $testname = "Coll-$locale-data$counter-StrCol";
231*0e209d39SAndroid Build Coastguard Worker	#write the results corresponding to this local,data pair
232*0e209d39SAndroid Build Coastguard Worker	$ICU->setAttribute("test"=> $testname);
233*0e209d39SAndroid Build Coastguard Worker	$ICU->setAttribute("iterations"=>1000);
234*0e209d39SAndroid Build Coastguard Worker	$ICU->setAttribute("time"=> $iStrCol);
235*0e209d39SAndroid Build Coastguard Worker	$root->appendChild($ICU);
236*0e209d39SAndroid Build Coastguard Worker
237*0e209d39SAndroid Build Coastguard Worker	my $Key = $doc->createElement("perfTestResult");
238*0e209d39SAndroid Build Coastguard Worker	my $testname = "Coll-$locale-data$counter-keyGen";
239*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("test"=> $testname);
240*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("iterations"=>1000);
241*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("time"=>$iKeyGen);
242*0e209d39SAndroid Build Coastguard Worker	$root->appendChild($Key);
243*0e209d39SAndroid Build Coastguard Worker
244*0e209d39SAndroid Build Coastguard Worker	my $JDK = $doc->createElement("perfTestResult");
245*0e209d39SAndroid Build Coastguard Worker	my $testname = "Coll-$locale-data$counter-StrCol-JDK";
246*0e209d39SAndroid Build Coastguard Worker	$JDK->setAttribute("test"=>$testname);
247*0e209d39SAndroid Build Coastguard Worker	$JDK->setAttribute("iterations"=>1000);
248*0e209d39SAndroid Build Coastguard Worker	$JDK->setAttribute("time"=>$wStrCol);
249*0e209d39SAndroid Build Coastguard Worker	$root->appendChild($JDK);
250*0e209d39SAndroid Build Coastguard Worker
251*0e209d39SAndroid Build Coastguard Worker	my $Key = $doc->createElement("perfTestResult");
252*0e209d39SAndroid Build Coastguard Worker	my $testname = "Coll-$locale-data$counter-keyGen-JDK";
253*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("test"=>$testname);
254*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("iterations"=>1000);
255*0e209d39SAndroid Build Coastguard Worker	$Key->setAttribute("time"=>$wKeyGen);
256*0e209d39SAndroid Build Coastguard Worker	$root->appendChild($Key);
257*0e209d39SAndroid Build Coastguard Worker	$counter++;
258*0e209d39SAndroid Build Coastguard Worker     }
259*0e209d39SAndroid Build Coastguard Worker   }
260*0e209d39SAndroid Build Coastguard Worker
261*0e209d39SAndroid Build Coastguard Worker
262*0e209d39SAndroid Build Coastguard Worker
263*0e209d39SAndroid Build Coastguard Worker#----------WRITE RESULTS TO perf.xml-----------------------
264*0e209d39SAndroid Build Coastguard Worker    $doc->setDocumentElement($root);
265*0e209d39SAndroid Build Coastguard Worker    open my $out_fh, '>', "perf.xml";
266*0e209d39SAndroid Build Coastguard Worker    print {$out_fh} $doc->toString;
267*0e209d39SAndroid Build Coastguard Worker}
268*0e209d39SAndroid Build Coastguard Worker
269*0e209d39SAndroid Build Coastguard Worker
270*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
271*0e209d39SAndroid Build Coastguard Worker# Append text to the global variable $OUT
272*0e209d39SAndroid Build Coastguard Workersub out {
273*0e209d39SAndroid Build Coastguard Worker   $OUT .= join('', @_);
274*0e209d39SAndroid Build Coastguard Worker}
275*0e209d39SAndroid Build Coastguard Worker
276*0e209d39SAndroid Build Coastguard Worker
277*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
278*0e209d39SAndroid Build Coastguard Worker# Measure a given test method with a give test pattern using the
279*0e209d39SAndroid Build Coastguard Worker# global run parameters.
280*0e209d39SAndroid Build Coastguard Worker#
281*0e209d39SAndroid Build Coastguard Worker# @param the method to run
282*0e209d39SAndroid Build Coastguard Worker# @param the pattern defining characters to test
283*0e209d39SAndroid Build Coastguard Worker# @param if >0 then the number of iterations per pass.  If <0 then
284*0e209d39SAndroid Build Coastguard Worker#        (negative of) the number of seconds per pass.
285*0e209d39SAndroid Build Coastguard Worker#
286*0e209d39SAndroid Build Coastguard Worker# @return a Dataset object, scaled by iterations per pass and
287*0e209d39SAndroid Build Coastguard Worker#         events per iteration, to give time per event
288*0e209d39SAndroid Build Coastguard Worker#
289*0e209d39SAndroid Build Coastguard Workersub measure2 {
290*0e209d39SAndroid Build Coastguard Worker    my @data = measure1(@_);
291*0e209d39SAndroid Build Coastguard Worker    my $iterPerPass = shift(@data);
292*0e209d39SAndroid Build Coastguard Worker    my $eventPerIter = shift(@data);
293*0e209d39SAndroid Build Coastguard Worker
294*0e209d39SAndroid Build Coastguard Worker    shift(@data) if (@data > 1); # discard first run
295*0e209d39SAndroid Build Coastguard Worker
296*0e209d39SAndroid Build Coastguard Worker    my $ds = Dataset->new(@data);
297*0e209d39SAndroid Build Coastguard Worker    $ds->setScale(1.0e-3 / ($iterPerPass * $eventPerIter));
298*0e209d39SAndroid Build Coastguard Worker    $ds;
299*0e209d39SAndroid Build Coastguard Worker}
300*0e209d39SAndroid Build Coastguard Worker
301*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
302*0e209d39SAndroid Build Coastguard Worker# Measure a given test method with a give test pattern using the
303*0e209d39SAndroid Build Coastguard Worker# global run parameters.
304*0e209d39SAndroid Build Coastguard Worker#
305*0e209d39SAndroid Build Coastguard Worker# @param the method to run
306*0e209d39SAndroid Build Coastguard Worker# @param the pattern defining characters to test
307*0e209d39SAndroid Build Coastguard Worker# @param if >0 then the number of iterations per pass.  If <0 then
308*0e209d39SAndroid Build Coastguard Worker#        (negative of) the number of seconds per pass.
309*0e209d39SAndroid Build Coastguard Worker#
310*0e209d39SAndroid Build Coastguard Worker# @return array of:
311*0e209d39SAndroid Build Coastguard Worker#         [0] iterations per pass
312*0e209d39SAndroid Build Coastguard Worker#         [1] events per iteration
313*0e209d39SAndroid Build Coastguard Worker#         [2..] ms reported for each pass, in order
314*0e209d39SAndroid Build Coastguard Worker#
315*0e209d39SAndroid Build Coastguard Workersub measure1 {
316*0e209d39SAndroid Build Coastguard Worker    my $testclass = shift;
317*0e209d39SAndroid Build Coastguard Worker    my $method = shift;
318*0e209d39SAndroid Build Coastguard Worker    my $pat = shift;
319*0e209d39SAndroid Build Coastguard Worker    my $iterCount = shift; # actually might be -seconds/pass
320*0e209d39SAndroid Build Coastguard Worker
321*0e209d39SAndroid Build Coastguard Worker    # is $iterCount actually -seconds/pass?
322*0e209d39SAndroid Build Coastguard Worker    if ($iterCount < 0) {
323*0e209d39SAndroid Build Coastguard Worker
324*0e209d39SAndroid Build Coastguard Worker        # calibrate: estimate ms/iteration
325*0e209d39SAndroid Build Coastguard Worker        print "Calibrating...";
326*0e209d39SAndroid Build Coastguard Worker        my @t = callJava($testclass, $method, $pat, -$CALIBRATE, 1);
327*0e209d39SAndroid Build Coastguard Worker        print "done.\n";
328*0e209d39SAndroid Build Coastguard Worker
329*0e209d39SAndroid Build Coastguard Worker        my @data = split(/\s+/, $t[0]->[2]);
330*0e209d39SAndroid Build Coastguard Worker        $data[0] *= 1.0e+3;
331*0e209d39SAndroid Build Coastguard Worker
332*0e209d39SAndroid Build Coastguard Worker        my $timePerIter = 1.0e-3 * $data[0] / $data[1];
333*0e209d39SAndroid Build Coastguard Worker
334*0e209d39SAndroid Build Coastguard Worker        # determine iterations/pass
335*0e209d39SAndroid Build Coastguard Worker        $iterCount = int(-$iterCount / $timePerIter + 0.5);
336*0e209d39SAndroid Build Coastguard Worker   }
337*0e209d39SAndroid Build Coastguard Worker
338*0e209d39SAndroid Build Coastguard Worker    # run passes
339*0e209d39SAndroid Build Coastguard Worker    print "Measuring $iterCount iterations x $NUMPASSES passes...";
340*0e209d39SAndroid Build Coastguard Worker    my @t = callJava($testclass, $method, $pat, $iterCount, $NUMPASSES);
341*0e209d39SAndroid Build Coastguard Worker    print "done.\n";
342*0e209d39SAndroid Build Coastguard Worker    my @ms = ();
343*0e209d39SAndroid Build Coastguard Worker    my @b; # scratch
344*0e209d39SAndroid Build Coastguard Worker    for my $a (@t) {
345*0e209d39SAndroid Build Coastguard Worker        # $a->[0]: method name, corresponds to $method
346*0e209d39SAndroid Build Coastguard Worker        # $a->[1]: 'begin' data, == $iterCount
347*0e209d39SAndroid Build Coastguard Worker        # $a->[2]: 'end' data, of the form <ms> <loops> <eventsPerIter>
348*0e209d39SAndroid Build Coastguard Worker        # $a->[3...]: gc messages from JVM during pass
349*0e209d39SAndroid Build Coastguard Worker        @b = split(/\s+/, $a->[2]);
350*0e209d39SAndroid Build Coastguard Worker        push(@ms, $b[0] * 1.0e+3);
351*0e209d39SAndroid Build Coastguard Worker    }
352*0e209d39SAndroid Build Coastguard Worker    my $eventsPerIter = $b[2];
353*0e209d39SAndroid Build Coastguard Worker
354*0e209d39SAndroid Build Coastguard Worker    my @ms_str = @ms;
355*0e209d39SAndroid Build Coastguard Worker    $ms_str[0] .= " (discarded)" if (@ms_str > 1);
356*0e209d39SAndroid Build Coastguard Worker
357*0e209d39SAndroid Build Coastguard Worker    ($iterCount, $eventsPerIter, @ms);
358*0e209d39SAndroid Build Coastguard Worker}
359*0e209d39SAndroid Build Coastguard Worker
360*0e209d39SAndroid Build Coastguard Worker#---------------------------------------------------------------------
361*0e209d39SAndroid Build Coastguard Worker# Invoke java to run $TESTCLASS, passing it the given parameters.
362*0e209d39SAndroid Build Coastguard Worker#
363*0e209d39SAndroid Build Coastguard Worker# @param the method to run
364*0e209d39SAndroid Build Coastguard Worker# @param the number of iterations, or if negative, the duration
365*0e209d39SAndroid Build Coastguard Worker#        in seconds.  If more than on pass is desired, pass in
366*0e209d39SAndroid Build Coastguard Worker#        a string, e.g., "100 100 100".
367*0e209d39SAndroid Build Coastguard Worker# @param the pattern defining characters to test
368*0e209d39SAndroid Build Coastguard Worker#
369*0e209d39SAndroid Build Coastguard Worker# @return an array of results.  Each result is an array REF
370*0e209d39SAndroid Build Coastguard Worker#         describing one pass.  The array REF contains:
371*0e209d39SAndroid Build Coastguard Worker#         ->[0]: The method name as reported
372*0e209d39SAndroid Build Coastguard Worker#         ->[1]: The params on the '= <meth> begin ...' line
373*0e209d39SAndroid Build Coastguard Worker#         ->[2]: The params on the '= <meth> end ...' line
374*0e209d39SAndroid Build Coastguard Worker#         ->[3..]: GC messages from the JVM, if any
375*0e209d39SAndroid Build Coastguard Worker#
376*0e209d39SAndroid Build Coastguard Workersub callJava {
377*0e209d39SAndroid Build Coastguard Worker    my $testclass = shift;
378*0e209d39SAndroid Build Coastguard Worker    my $method = shift;
379*0e209d39SAndroid Build Coastguard Worker    my $pat = shift;
380*0e209d39SAndroid Build Coastguard Worker    my $n = shift;
381*0e209d39SAndroid Build Coastguard Worker    my $passes = shift;
382*0e209d39SAndroid Build Coastguard Worker
383*0e209d39SAndroid Build Coastguard Worker    my $n = ($n < 0) ? "-t ".(-$n) : "-i ".$n;
384*0e209d39SAndroid Build Coastguard Worker
385*0e209d39SAndroid Build Coastguard Worker    my $cmd = "java -classpath $CLASSPATH $testclass $method $n -p $passes -L @$pat[0] \"@$pat[1]\" \"@$pat[2]\" -r $THREADS";
386*0e209d39SAndroid Build Coastguard Worker    print "[$cmd]\n"; # for debugging
387*0e209d39SAndroid Build Coastguard Worker    open(PIPE, "$cmd|") or die "Can't run \"$cmd\"";
388*0e209d39SAndroid Build Coastguard Worker    my @out;
389*0e209d39SAndroid Build Coastguard Worker    while (<PIPE>) {
390*0e209d39SAndroid Build Coastguard Worker        push(@out, $_);
391*0e209d39SAndroid Build Coastguard Worker    }
392*0e209d39SAndroid Build Coastguard Worker    close(PIPE) or die "Java failed: \"$cmd\"";
393*0e209d39SAndroid Build Coastguard Worker
394*0e209d39SAndroid Build Coastguard Worker    @out = grep(!/^\#/, @out);  # filter out comments
395*0e209d39SAndroid Build Coastguard Worker
396*0e209d39SAndroid Build Coastguard Worker    #print "[", join("\n", @out), "]\n";
397*0e209d39SAndroid Build Coastguard Worker
398*0e209d39SAndroid Build Coastguard Worker    my @results;
399*0e209d39SAndroid Build Coastguard Worker    my $method = '';
400*0e209d39SAndroid Build Coastguard Worker    my $data = [];
401*0e209d39SAndroid Build Coastguard Worker    foreach (@out) {
402*0e209d39SAndroid Build Coastguard Worker        next unless (/\S/);
403*0e209d39SAndroid Build Coastguard Worker
404*0e209d39SAndroid Build Coastguard Worker        if (/^=\s*(\w+)\s*(\w+)\s*(.*)/) {
405*0e209d39SAndroid Build Coastguard Worker            my ($m, $state, $d) = ($1, $2, $3);
406*0e209d39SAndroid Build Coastguard Worker            #print "$_ => [[$m $state $data]]\n";
407*0e209d39SAndroid Build Coastguard Worker            if ($state eq 'begin') {
408*0e209d39SAndroid Build Coastguard Worker                die "$method was begun but not finished" if ($method);
409*0e209d39SAndroid Build Coastguard Worker                $method = $m;
410*0e209d39SAndroid Build Coastguard Worker                push(@$data, $d);
411*0e209d39SAndroid Build Coastguard Worker                push(@$data, ''); # placeholder for end data
412*0e209d39SAndroid Build Coastguard Worker            } elsif ($state eq 'end') {
413*0e209d39SAndroid Build Coastguard Worker                if ($m ne $method) {
414*0e209d39SAndroid Build Coastguard Worker                    die "$method end does not match: $_";
415*0e209d39SAndroid Build Coastguard Worker                }
416*0e209d39SAndroid Build Coastguard Worker                $data->[1] = $d; # insert end data at [1]
417*0e209d39SAndroid Build Coastguard Worker                #print "#$method:", join(";",@$data), "\n";
418*0e209d39SAndroid Build Coastguard Worker                unshift(@$data, $method); # add method to start
419*0e209d39SAndroid Build Coastguard Worker
420*0e209d39SAndroid Build Coastguard Worker                push(@results, $data);
421*0e209d39SAndroid Build Coastguard Worker                $method = '';
422*0e209d39SAndroid Build Coastguard Worker                $data = [];
423*0e209d39SAndroid Build Coastguard Worker            } else {
424*0e209d39SAndroid Build Coastguard Worker                die "Can't parse: $_";
425*0e209d39SAndroid Build Coastguard Worker           }
426*0e209d39SAndroid Build Coastguard Worker        }
427*0e209d39SAndroid Build Coastguard Worker       elsif (/^\[/) {
428*0e209d39SAndroid Build Coastguard Worker            if ($method) {
429*0e209d39SAndroid Build Coastguard Worker                push(@$data, $_);
430*0e209d39SAndroid Build Coastguard Worker            } else {
431*0e209d39SAndroid Build Coastguard Worker                # ignore extraneous GC notices
432*0e209d39SAndroid Build Coastguard Worker            }
433*0e209d39SAndroid Build Coastguard Worker        }
434*0e209d39SAndroid Build Coastguard Worker        else {
435*0e209d39SAndroid Build Coastguard Worker            die "Can't parse: $_";
436*0e209d39SAndroid Build Coastguard Worker        }
437*0e209d39SAndroid Build Coastguard Worker    }
438*0e209d39SAndroid Build Coastguard Worker
439*0e209d39SAndroid Build Coastguard Worker    die "$method was begun but not finished" if ($method);
440*0e209d39SAndroid Build Coastguard Worker
441*0e209d39SAndroid Build Coastguard Worker    @results;
442*0e209d39SAndroid Build Coastguard Worker}
443*0e209d39SAndroid Build Coastguard Worker
444*0e209d39SAndroid Build Coastguard Worker#-----------------------------------------------------------------------------------
445*0e209d39SAndroid Build Coastguard Worker#  doKeyGenTimes($Command_to_run, $time, $key_length)
446*0e209d39SAndroid Build Coastguard Worker#       Do a key-generation test and return the time and key length/char values.
447*0e209d39SAndroid Build Coastguard Worker#
448*0e209d39SAndroid Build Coastguard Workersub doKeyTimes($$$) {
449*0e209d39SAndroid Build Coastguard Worker   # print "$_[0]\n";
450*0e209d39SAndroid Build Coastguard Worker   local($x) = `$_[0]`;                  # execute the collperf command.
451*0e209d39SAndroid Build Coastguard Worker   ($_[1], $_[2]) = split(/\,/, $x);     # collperf returns "time, keylength" string.
452*0e209d39SAndroid Build Coastguard Worker}
453*0e209d39SAndroid Build Coastguard Worker
454*0e209d39SAndroid Build Coastguard Worker
455*0e209d39SAndroid Build Coastguard Worker#eof
456