| OLD | NEW |
| (Empty) |
| 1 #!/usr/local/bin/perl | |
| 2 # *********************************************************************** | |
| 3 # * COPYRIGHT: | |
| 4 # * Copyright (c) 2002-2013, International Business Machines Corporation | |
| 5 # * and others. All Rights Reserved. | |
| 6 # *********************************************************************** | |
| 7 | |
| 8 use strict; | |
| 9 | |
| 10 #use Dataset; | |
| 11 use Format; | |
| 12 use Output; | |
| 13 | |
| 14 my $VERBOSE = 0; | |
| 15 my $DEBUG = 1; | |
| 16 my $start_l = ""; #formatting help | |
| 17 my $end_l = ""; | |
| 18 my @testArgs; # different kinds of tests we want to do | |
| 19 my $datadir = "data"; | |
| 20 my $extraArgs; # stuff that always gets passed to the test program | |
| 21 | |
| 22 | |
| 23 my $iterCount = 0; | |
| 24 my $NUMPASSES = 4; | |
| 25 my $TIME = 2; | |
| 26 my $ITERATIONS; #Added by Doug | |
| 27 my $DATADIR; | |
| 28 | |
| 29 sub setupOptions { | |
| 30 my %options = %{shift @_}; | |
| 31 | |
| 32 if($options{"time"}) { | |
| 33 $TIME = $options{"time"}; | |
| 34 } | |
| 35 | |
| 36 if($options{"passes"}) { | |
| 37 $NUMPASSES = $options{"passes"}; | |
| 38 } | |
| 39 | |
| 40 if($options{"dataDir"}) { | |
| 41 $DATADIR = $options{"dataDir"}; | |
| 42 } | |
| 43 | |
| 44 # Added by Doug | |
| 45 if ($options{"iterations"}) { | |
| 46 $ITERATIONS = $options{"iterations"}; | |
| 47 } | |
| 48 } | |
| 49 | |
| 50 sub runTests { | |
| 51 my $options = shift; | |
| 52 my @programs; | |
| 53 my $tests = shift; | |
| 54 my %datafiles; | |
| 55 if($#_ >= 0) { # maybe no files/locales | |
| 56 my $datafiles = shift; | |
| 57 if($datafiles) { | |
| 58 %datafiles = %{$datafiles}; | |
| 59 } | |
| 60 } | |
| 61 setupOutput($options); | |
| 62 setupOptions($options); | |
| 63 | |
| 64 my($locale, $iter, $data, $program, $args, $variable); | |
| 65 # | |
| 66 # Outer loop runs through the locales to test | |
| 67 # | |
| 68 if (%datafiles) { | |
| 69 foreach $locale (sort keys %datafiles ) { | |
| 70 foreach $data (@{ $datafiles{$locale} }) { | |
| 71 closeTable; | |
| 72 my $locdata = ""; | |
| 73 if(!($locale eq "")) { | |
| 74 $locdata = "<b>Locale:</b> $locale<br>"; | |
| 75 } | |
| 76 $locdata .= "<b>Datafile:</b> $data<br>"; | |
| 77 startTest($locdata); | |
| 78 | |
| 79 if($DATADIR) { | |
| 80 compareLoop ($tests, $locale, $DATADIR."/".$data); | |
| 81 } else { | |
| 82 compareLoop ($tests, $locale, $data); | |
| 83 } | |
| 84 } | |
| 85 } | |
| 86 } else { | |
| 87 compareLoop($tests); | |
| 88 } | |
| 89 closeOutput(); | |
| 90 } | |
| 91 | |
| 92 sub compareLoop { | |
| 93 my $tests = shift; | |
| 94 #my @tests = @{$tests}; | |
| 95 my %tests = %{$tests}; | |
| 96 my $locale = shift; | |
| 97 my $datafile = shift; | |
| 98 my $locAndData = ""; | |
| 99 if($locale) { | |
| 100 $locAndData .= " -L \"$locale\""; | |
| 101 } | |
| 102 if($datafile) { | |
| 103 $locAndData .= " -f $datafile"; | |
| 104 } | |
| 105 | |
| 106 my $args; | |
| 107 my ($i, $j, $aref); | |
| 108 foreach $i ( sort keys %tests ) { | |
| 109 debug("Test: $i\n"); | |
| 110 $aref = $tests{$i}; | |
| 111 my @timedata; | |
| 112 my @iterPerPass; | |
| 113 my @noopers; | |
| 114 my @noevents; | |
| 115 | |
| 116 my $program; | |
| 117 my @argsAndTest; | |
| 118 for $j ( 0 .. $#{$aref} ) { | |
| 119 # first we calibrate. Use time from somewhere | |
| 120 # first test is used for calibration | |
| 121 ($program, @argsAndTest) = split(/,/, @{ $tests{$i} }[$j]); | |
| 122 #Modified by Doug | |
| 123 my $commandLine; | |
| 124 if ($ITERATIONS) { | |
| 125 $commandLine = "$program -i $ITERATIONS -p $NUMPASSES $locAndData @argsA
ndTest"; | |
| 126 } else { | |
| 127 $commandLine = "$program -t $TIME -p $NUMPASSES $locAndData @argsAndTest
"; | |
| 128 } | |
| 129 #my $commandLine = "$program -i 5 -p $NUMPASSES $locAndData @argsAndTest"; | |
| 130 my @res = measure1($commandLine); | |
| 131 store("$i, $program @argsAndTest", @res); | |
| 132 | |
| 133 push(@iterPerPass, shift(@res)); | |
| 134 push(@noopers, shift(@res)); | |
| 135 my @data = @{ shift(@res) }; | |
| 136 if($#res >= 0) { | |
| 137 push(@noevents, shift(@res)); | |
| 138 } | |
| 139 | |
| 140 shift(@data) if (@data > 1); # discard first run | |
| 141 | |
| 142 #debug("data is @data\n"); | |
| 143 my $ds = Dataset->new(@data); | |
| 144 | |
| 145 push(@timedata, $ds); | |
| 146 } | |
| 147 | |
| 148 outputRow($i, \@iterPerPass, \@noopers, \@timedata, \@noevents); | |
| 149 } | |
| 150 | |
| 151 } | |
| 152 | |
| 153 #--------------------------------------------------------------------- | |
| 154 # Measure a given test method with a give test pattern using the | |
| 155 # global run parameters. | |
| 156 # | |
| 157 # @param the method to run | |
| 158 # @param the pattern defining characters to test | |
| 159 # @param if >0 then the number of iterations per pass. If <0 then | |
| 160 # (negative of) the number of seconds per pass. | |
| 161 # | |
| 162 # @return array of: | |
| 163 # [0] iterations per pass | |
| 164 # [1] events per iteration | |
| 165 # [2..] ms reported for each pass, in order | |
| 166 # | |
| 167 sub measure1 { | |
| 168 # run passes | |
| 169 my @t = callProg(shift); #"$program $args $argsAndTest"); | |
| 170 my @ms = (); | |
| 171 my @b; # scratch | |
| 172 for my $a (@t) { | |
| 173 # $a->[0]: method name, corresponds to $method | |
| 174 # $a->[1]: 'begin' data, == $iterCount | |
| 175 # $a->[2]: 'end' data, of the form <ms> <eventsPerIter> | |
| 176 # $a->[3...]: gc messages from JVM during pass | |
| 177 @b = split(/\s+/, $a->[2]); | |
| 178 #push(@ms, $b[0]); | |
| 179 push(@ms, shift(@b)); | |
| 180 } | |
| 181 my $iterCount = shift(@b); | |
| 182 my $operationsPerIter = shift(@b); | |
| 183 my $eventsPerIter; | |
| 184 if($#b >= 0) { | |
| 185 $eventsPerIter = shift(@b); | |
| 186 } | |
| 187 | |
| 188 # out("Iterations per pass: $iterCount<BR>\n"); | |
| 189 # out("Events per iteration: $eventsPerIter<BR>\n"); | |
| 190 # debug("Iterations per pass: $iterCount<BR>\n"); | |
| 191 # if($eventsPerIter) { | |
| 192 # debug("Events per iteration: $eventsPerIter<BR>\n"); | |
| 193 # } | |
| 194 | |
| 195 my @ms_str = @ms; | |
| 196 $ms_str[0] .= " (discarded)" if (@ms_str > 1); | |
| 197 # out("Raw times (ms/pass): ", join(", ", @ms_str), "<BR>\n"); | |
| 198 debug("Raw times (ms/pass): ", join(", ", @ms_str), "<BR>\n"); | |
| 199 if($eventsPerIter) { | |
| 200 ($iterCount, $operationsPerIter, \@ms, $eventsPerIter); | |
| 201 } else { | |
| 202 ($iterCount, $operationsPerIter, \@ms); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 | |
| 207 | |
| 208 #--------------------------------------------------------------------- | |
| 209 # Measure a given test method with a give test pattern using the | |
| 210 # global run parameters. | |
| 211 # | |
| 212 # @param the method to run | |
| 213 # @param the pattern defining characters to test | |
| 214 # @param if >0 then the number of iterations per pass. If <0 then | |
| 215 # (negative of) the number of seconds per pass. | |
| 216 # | |
| 217 # @return a Dataset object, scaled by iterations per pass and | |
| 218 # events per iteration, to give time per event | |
| 219 # | |
| 220 sub measure2 { | |
| 221 my @res = measure1(@_); | |
| 222 my $iterPerPass = shift(@res); | |
| 223 my $operationsPerIter = shift(@res); | |
| 224 my @data = @{ shift(@res) }; | |
| 225 my $eventsPerIter = shift(@res); | |
| 226 | |
| 227 | |
| 228 shift(@data) if (@data > 1); # discard first run | |
| 229 | |
| 230 my $ds = Dataset->new(@data); | |
| 231 #$ds->setScale(1.0e-3 / ($iterPerPass * $operationsPerIter)); | |
| 232 ($ds, $iterPerPass, $operationsPerIter, $eventsPerIter); | |
| 233 } | |
| 234 | |
| 235 | |
| 236 #--------------------------------------------------------------------- | |
| 237 # Invoke program and capture results, passing it the given parameters. | |
| 238 # | |
| 239 # @param the method to run | |
| 240 # @param the number of iterations, or if negative, the duration | |
| 241 # in seconds. If more than on pass is desired, pass in | |
| 242 # a string, e.g., "100 100 100". | |
| 243 # @param the pattern defining characters to test | |
| 244 # | |
| 245 # @return an array of results. Each result is an array REF | |
| 246 # describing one pass. The array REF contains: | |
| 247 # ->[0]: The method name as reported | |
| 248 # ->[1]: The params on the '= <meth> begin ...' line | |
| 249 # ->[2]: The params on the '= <meth> end ...' line | |
| 250 # ->[3..]: GC messages from the JVM, if any | |
| 251 # | |
| 252 sub callProg { | |
| 253 my $cmd = shift; | |
| 254 #my $pat = shift; | |
| 255 #my $n = shift; | |
| 256 | |
| 257 #my $cmd = "java -cp c:\\dev\\myicu4j\\classes $TESTCLASS $method $n $pat"; | |
| 258 debug( "[$cmd]\n"); # for debugging | |
| 259 open(PIPE, "$cmd|") or die "Can't run \"$cmd\""; | |
| 260 my @out; | |
| 261 while (<PIPE>) { | |
| 262 push(@out, $_); | |
| 263 } | |
| 264 close(PIPE) or die "Program failed: \"$cmd\""; | |
| 265 | |
| 266 @out = grep(!/^\#/, @out); # filter out comments | |
| 267 | |
| 268 #debug( "[", join("\n", @out), "]\n"); | |
| 269 | |
| 270 my @results; | |
| 271 my $method = ''; | |
| 272 my $data = []; | |
| 273 foreach (@out) { | |
| 274 next unless (/\S/); | |
| 275 | |
| 276 if (/^=\s*(\w+)\s*(\w+)\s*(.*)/) { | |
| 277 my ($m, $state, $d) = ($1, $2, $3); | |
| 278 #debug ("$_ => [[$m $state !!!$d!!! $data ]]\n"); | |
| 279 if ($state eq 'begin') { | |
| 280 die "$method was begun but not finished" if ($method); | |
| 281 $method = $m; | |
| 282 push(@$data, $d); | |
| 283 push(@$data, ''); # placeholder for end data | |
| 284 } elsif ($state eq 'end') { | |
| 285 if ($m ne $method) { | |
| 286 die "$method end does not match: $_"; | |
| 287 } | |
| 288 $data->[1] = $d; # insert end data at [1] | |
| 289 #debug( "#$method:", join(";",@$data), "\n"); | |
| 290 unshift(@$data, $method); # add method to start | |
| 291 push(@results, $data); | |
| 292 $method = ''; | |
| 293 $data = []; | |
| 294 } else { | |
| 295 die "Can't parse: $_"; | |
| 296 } | |
| 297 } | |
| 298 | |
| 299 elsif (/^\[/) { | |
| 300 if ($method) { | |
| 301 push(@$data, $_); | |
| 302 } else { | |
| 303 # ignore extraneous GC notices | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 else { | |
| 308 # die "Can't parse: $_"; | |
| 309 } | |
| 310 } | |
| 311 | |
| 312 die "$method was begun but not finished" if ($method); | |
| 313 | |
| 314 @results; | |
| 315 } | |
| 316 | |
| 317 sub debug { | |
| 318 my $message; | |
| 319 if($DEBUG != 0) { | |
| 320 foreach $message (@_) { | |
| 321 print STDERR "$message"; | |
| 322 } | |
| 323 } | |
| 324 } | |
| 325 | |
| 326 sub measure1Alan { | |
| 327 #Added here, was global | |
| 328 my $CALIBRATE = 2; # duration in seconds for initial calibration | |
| 329 | |
| 330 my $method = shift; | |
| 331 my $pat = shift; | |
| 332 my $iterCount = shift; # actually might be -seconds/pass | |
| 333 | |
| 334 out("<P>Measuring $method using $pat, "); | |
| 335 if ($iterCount > 0) { | |
| 336 out("$iterCount iterations/pass, $NUMPASSES passes</P>\n"); | |
| 337 } else { | |
| 338 out(-$iterCount, " seconds/pass, $NUMPASSES passes</P>\n"); | |
| 339 } | |
| 340 | |
| 341 # is $iterCount actually -seconds? | |
| 342 if ($iterCount < 0) { | |
| 343 | |
| 344 # calibrate: estimate ms/iteration | |
| 345 print "Calibrating..."; | |
| 346 my @t = callJava($method, $pat, -$CALIBRATE); | |
| 347 print "done.\n"; | |
| 348 | |
| 349 my @data = split(/\s+/, $t[0]->[2]); | |
| 350 my $timePerIter = 1.0e-3 * $data[0] / $data[2]; | |
| 351 | |
| 352 # determine iterations/pass | |
| 353 $iterCount = int(-$iterCount / $timePerIter + 0.5); | |
| 354 | |
| 355 out("<P>Calibration pass ($CALIBRATE sec): "); | |
| 356 out("$data[0] ms, "); | |
| 357 out("$data[2] iterations = "); | |
| 358 out(formatSeconds(4, $timePerIter), "/iteration<BR>\n"); | |
| 359 } | |
| 360 | |
| 361 # run passes | |
| 362 print "Measuring $iterCount iterations x $NUMPASSES passes..."; | |
| 363 my @t = callJava($method, $pat, "$iterCount " x $NUMPASSES); | |
| 364 print "done.\n"; | |
| 365 my @ms = (); | |
| 366 my @b; # scratch | |
| 367 for my $a (@t) { | |
| 368 # $a->[0]: method name, corresponds to $method | |
| 369 # $a->[1]: 'begin' data, == $iterCount | |
| 370 # $a->[2]: 'end' data, of the form <ms> <eventsPerIter> | |
| 371 # $a->[3...]: gc messages from JVM during pass | |
| 372 @b = split(/\s+/, $a->[2]); | |
| 373 push(@ms, $b[0]); | |
| 374 } | |
| 375 my $eventsPerIter = $b[1]; | |
| 376 | |
| 377 out("Iterations per pass: $iterCount<BR>\n"); | |
| 378 out("Events per iteration: $eventsPerIter<BR>\n"); | |
| 379 | |
| 380 my @ms_str = @ms; | |
| 381 $ms_str[0] .= " (discarded)" if (@ms_str > 1); | |
| 382 out("Raw times (ms/pass): ", join(", ", @ms_str), "<BR>\n"); | |
| 383 | |
| 384 ($iterCount, $eventsPerIter, @ms); | |
| 385 } | |
| 386 | |
| 387 | |
| 388 1; | |
| 389 | |
| 390 #eof | |
| OLD | NEW |