]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/perf/perldriver/Output.pm
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / perf / perldriver / Output.pm
1 #!/usr/local/bin/perl
2
3 # ********************************************************************
4 # * Copyright (C) 2016 and later: Unicode, Inc. and others.
5 # * License & terms of use: http://www.unicode.org/copyright.html#License
6 # ********************************************************************
7 # ********************************************************************
8 # * COPYRIGHT:
9 # * Copyright (c) 2002, International Business Machines Corporation and
10 # * others. All Rights Reserved.
11 # ********************************************************************
12
13
14 use strict;
15
16 use Dataset;
17
18 my $TABLEATTR = 'BORDER="1" CELLPADDING="4" CELLSPACING="0"';
19 my $outType = "HTML";
20 my $html = "noName";
21 my $inTable;
22 my @headers;
23 my @timetypes = ("mean per op", "error per op", "events", "per event");
24 my %raw;
25 my $current = "";
26 my $exp = 0;
27 my $mult = 1e9; #use nanoseconds
28 my $perc = 100; #for percent
29 my $printEvents = 0;
30 my $legend = "<a name=\"Legend\">\n<h2>Table legend</h2></a><ul>";
31 my $legendDone = 0;
32 my %options;
33 my $operationIs = "operation";
34 my $eventIs = "event";
35
36 sub startTest {
37 $current = shift;
38 $exp = 0;
39 outputData($current);
40 }
41
42 sub printLeg {
43 if(!$legendDone) {
44 my $message;
45 foreach $message (@_) {
46 $legend .= "<li>".$message."</li>\n";
47 }
48 }
49 }
50
51 sub outputDist {
52 my $value = shift;
53 my $percent = shift;
54 my $mean = $value->getMean;
55 my $error = $value->getError;
56 print HTML "<td class=\"";
57 if($mean > 0) {
58 print HTML "value";
59 } else {
60 print HTML "worse";
61 }
62 print HTML "\">";
63 if($percent) {
64 print HTML formatPercent(2, $mean);
65 } else {
66 print HTML formatNumber(2, $mult, $mean);
67 }
68 print HTML "</td>\n";
69 print HTML "<td class=\"";
70 if((($error*$mult < 10)&&!$percent) || (($error<10)&&$percent)) {
71 print HTML "error";
72 } else {
73 print HTML "errorLarge";
74 }
75 print HTML "\">&plusmn;";
76 if($percent) {
77 print HTML formatPercent(2, $error);
78 } else {
79 print HTML formatNumber(2, $mult, $error);
80 }
81 print HTML "</td>\n";
82 }
83
84 sub outputValue {
85 my $value = shift;
86 print HTML "<td class=\"sepvalue\">";
87 print HTML $value;
88 #print HTML formatNumber(2, 1, $value);
89 print HTML "</td>\n";
90 }
91
92 sub startTable {
93 #my $printEvents = shift;
94 $inTable = 1;
95 my $i;
96 print HTML "<table $TABLEATTR>\n";
97 print HTML "<tbody>\n";
98 if($#headers >= 0) {
99 my ($header, $i);
100 print HTML "<tr>\n";
101 print HTML "<th rowspan=\"2\" class=\"testNameHeader\"><a href=\"#TestName\">Test Name</a></th>\n";
102 print HTML "<th rowspan=\"2\" class=\"testNameHeader\"><a href=\"#Ops\">Ops</a></th>\n";
103 printLeg("<a name=\"Test Name\">TestName</a> - name of the test as set by the test writer\n", "<a name=\"Ops\">Ops</a> - number of ".$operationIs."s per iteration\n");
104 if(!$printEvents) {
105 print HTML "<th colspan=".((4*($#headers+1))-2)." class=\"sourceType\">Per Operation</th>\n";
106 } else {
107 print HTML "<th colspan=".((2*($#headers+1))-2)." class=\"sourceType\">Per Operation</th>\n";
108 print HTML "<th colspan=".((5*($#headers+1))-2)." class=\"sourceType\">Per Event</th>\n";
109 }
110 print HTML "</tr>\n<tr>\n";
111 if(!$printEvents) {
112 foreach $header (@headers) {
113 print HTML "<th class=\"source\" colspan=2><a href=\"#meanop_$header\">$header<br>/op</a></th>\n";
114 printLeg("<a name=\"meanop_$header\">$header /op</a> - mean time and error for $header per $operationIs");
115 }
116 }
117 for $i (1 .. $#headers) {
118 print HTML "<th class=\"source\" colspan=2><a href=\"#mean_op_$i\">ratio $i<br>/op</a></th>\n";
119 printLeg("<a name=\"mean_op_$i\">ratio $i /op</a> - ratio and error of per $operationIs time, calculated as: (($headers[0] - $headers[$i])/$headers[$i])*100%, mean value");
120 }
121 if($printEvents) {
122 foreach $header (@headers) {
123 print HTML "<th class=\"source\"><a href=\"#events_$header\">$header<br>events</a></th>\n";
124 printLeg("<a name=\"events_$header\">$header events</a> - number of ".$eventIs."s for $header per iteration");
125 }
126 foreach $header (@headers) {
127 print HTML "<th class=\"source\" colspan=2><a href=\"#mean_ev_$header\">$header<br>/ev</a></th>\n";
128 printLeg("<a name=\"mean_ev_$header\">$header /ev</a> - mean time and error for $header per $eventIs");
129 }
130 for $i (1 .. $#headers) {
131 print HTML "<th class=\"source\" colspan=2><a href=\"#mean_ev_$i\">ratio $i<br>/ev</a></th>\n";
132 printLeg("<a name=\"mean_ev_$i\">ratio $i /ev</a> - ratio and error of per $eventIs time, calculated as: (($headers[0] - $headers[$i])/$headers[$i])*100%, mean value");
133 }
134 }
135 print HTML "</tr>\n";
136 }
137 $legendDone = 1;
138 }
139
140 sub closeTable {
141 if($inTable) {
142 undef $inTable;
143 print HTML "</tr>\n";
144 print HTML "</tbody>";
145 print HTML "</table>\n";
146 }
147 }
148
149 sub newRow {
150 if(!$inTable) {
151 startTable;
152 } else {
153 print HTML "</tr>\n";
154 }
155 print HTML "<tr>";
156 }
157
158 sub outputData {
159 if($inTable) {
160 my $msg = shift;
161 my $align = shift;
162 print HTML "<td";
163 if($align) {
164 print HTML " align = $align>";
165 } else {
166 print HTML ">";
167 }
168 print HTML "$msg";
169 print HTML "</td>";
170 } else {
171 my $message;
172 foreach $message (@_) {
173 print HTML "$message";
174 }
175 }
176 }
177
178 sub setupOutput {
179 my $date = localtime;
180 my $options = shift;
181 %options = %{ $options };
182 my $title = $options{ "title" };
183 my $headers = $options{ "headers" };
184 if($options{ "operationIs" }) {
185 $operationIs = $options{ "operationIs" };
186 }
187 if($options{ "eventIs" }) {
188 $eventIs = $options{ "eventIs" };
189 }
190 @headers = split(/ /, $headers);
191 my ($t, $rest);
192 ($t, $rest) = split(/\.\w+/, $0);
193 $t =~ /^.*\W(\w+)$/;
194 $t = $1;
195 if($outType eq 'HTML') {
196 $html = $date;
197 $html =~ s/://g; # ':' illegal
198 $html =~ s/\s*\d+$//; # delete year
199 $html =~ s/^\w+\s*//; # delete dow
200 $html = "$t $html.html";
201 if($options{ "outputDir" }) {
202 $html = $options{ "outputDir" }."/".$html;
203 }
204 $html =~ s/ /_/g;
205
206 open(HTML,">$html") or die "Can't write to $html: $!";
207
208 #<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
209 print HTML <<EOF;
210 <HTML>
211 <HEAD>
212 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
213 <TITLE>$title</TITLE>
214 <style>
215 <!--
216 body { font-size: 10pt; font-family: sans-serif }
217 th { font-size: 10pt; border: 0 solid #000080; padding: 5 }
218 th.testNameHeader { border-width: 1 }
219 th.testName { text-align: left; border-left-width: 1; border-right-width: 1;
220 border-bottom-width: 1 }
221 th.source { border-right-width: 1; border-bottom-width: 1 }
222 th.sourceType { border-right-width: 1; border-top-width: 1; border-bottom-width: 1 }
223 td { font-size: 10pt; text-align: Right; border: 0 solid #000080; padding: 5 }
224 td.string { text-align: Left; border-bottom-width:1; border-right-width:1 }
225 td.sepvalue { border-bottom-width: 1; border-right-width: 1 }
226 td.value { border-bottom-width: 1 }
227 td.worse { color: #FF0000; font-weight: bold; border-bottom-width: 1 }
228 td.error { font-size: 75%; border-right-width: 1; border-bottom-width: 1 }
229 td.errorLarge { font-size: 75%; color: #FF0000; font-weight: bold; border-right-width: 1;
230 border-bottom-width: 1 }
231 A:link { color: black; font-weight: normal; text-decoration: none} /* unvisited links */
232 A:visited { color: blue; font-weight: normal; text-decoration: none } /* visited links */
233 A:hover { color: red; font-weight: normal; text-decoration: none } /* user hovers */
234 A:active { color: lime; font-weight: normal; text-decoration: none } /* active links */
235 -->
236 </style>
237 </HEAD>
238 <BODY bgcolor="#FFFFFF" LINK="#006666" VLINK="#000000">
239 EOF
240 print HTML "<H1>$title</H1>\n";
241
242 #print HTML "<H2>$TESTCLASS</H2>\n";
243 }
244 }
245
246 sub closeOutput {
247 if($outType eq 'HTML') {
248 if($inTable) {
249 closeTable;
250 }
251 $legend .= "</ul>\n";
252 print HTML $legend;
253 outputRaw();
254 print HTML <<EOF;
255 </BODY>
256 </HTML>
257 EOF
258 close(HTML) or die "Can't close $html: $!";
259 }
260 }
261
262
263 sub outputRaw {
264 print HTML "<h2>Raw data</h2>";
265 my $key;
266 my $i;
267 my $j;
268 my $k;
269 print HTML "<table $TABLEATTR>\n";
270 for $key (sort keys %raw) {
271 my $printkey = $key;
272 $printkey =~ s/\<br\>/ /g;
273 if($printEvents) {
274 if($key ne "") {
275 print HTML "<tr><th class=\"testNameHeader\" colspan = 7>$printkey</td></tr>\n"; # locale and data file
276 }
277 print HTML "<tr><th class=\"testName\">test name</th><th class=\"testName\">interesting arguments</th><th class=\"testName\">iterations</th><th class=\"testName\">operations</th><th class=\"testName\">mean time (ns)</th><th class=\"testName\">error (ns)</th><th class=\"testName\">events</th></tr>\n";
278 } else {
279 if($key ne "") {
280 print HTML "<tr><th class=\"testName\" colspan = 6>$printkey</td></tr>\n"; # locale and data file
281 }
282 print HTML "<tr><th class=\"testName\">test name</th><th class=\"testName\">interesting arguments</th><th class=\"testName\">iterations</th><th class=\"testName\">operations</th><th class=\"testName\">mean time (ns)</th><th class=\"testName\">error (ns)</th></tr>\n";
283 }
284 $printkey =~ s/[\<\>\/ ]//g;
285
286 my %done;
287 for $i ( $raw{$key} ) {
288 print HTML "<tr>";
289 for $j ( @$i ) {
290 my ($test, $args);
291 ($test, $args) = split(/,/, shift(@$j));
292
293 print HTML "<th class=\"testName\">";
294 if(!$done{$test}) {
295 print HTML "<a name=\"".$printkey."_".$test."\">".$test."</a>";
296 $done{$test} = 1;
297 } else {
298 print HTML $test;
299 }
300 print HTML "</th>";
301
302 print HTML "<td class=\"string\">".$args."</td>";
303
304 print HTML "<td class=\"sepvalue\">".shift(@$j)."</td>";
305 print HTML "<td class=\"sepvalue\">".shift(@$j)."</td>";
306
307 my @data = @{ shift(@$j) };
308 my $ds = Dataset->new(@data);
309 print HTML "<td class=\"sepvalue\">".formatNumber(4, $mult, $ds->getMean)."</td><td class=\"sepvalue\">".formatNumber(4, $mult, $ds->getError)."</td>";
310 if($#{ $j } >= 0) {
311 print HTML "<td class=\"sepvalue\">".shift(@$j)."</td>";
312 }
313 print HTML "</tr>\n";
314 }
315 }
316 }
317 }
318
319 sub store {
320 $raw{$current}[$exp++] = [@_];
321 }
322
323 sub outputRow {
324 #$raw{$current}[$exp++] = [@_];
325 my $testName = shift;
326 my @iterPerPass = @{shift(@_)};
327 my @noopers = @{shift(@_)};
328 my @timedata = @{shift(@_)};
329 my @noevents;
330 if($#_ >= 0) {
331 @noevents = @{shift(@_)};
332 }
333 if(!$inTable) {
334 if(@noevents) {
335 $printEvents = 1;
336 startTable;
337 } else {
338 startTable;
339 }
340 }
341 debug("No events: @noevents, $#noevents\n");
342
343 my $j;
344 my $loc = $current;
345 $loc =~ s/\<br\>/ /g;
346 $loc =~ s/[\<\>\/ ]//g;
347
348 # Finished one row of results. Outputting
349 newRow;
350 #outputData($testName, "LEFT");
351 print HTML "<th class=\"testName\"><a href=\"#".$loc."_".$testName."\">$testName</a></th>\n";
352 #outputData($iterCount);
353 #outputData($noopers[0], "RIGHT");
354 outputValue($noopers[0]);
355
356 if(!$printEvents) {
357 for $j ( 0 .. $#timedata ) {
358 my $perOperation = $timedata[$j]->divideByScalar($iterPerPass[$j]*$noopers[$j]); # time per operation
359 #debug("Time per operation: ".formatSeconds(4, $perOperation->getMean, $perOperation->getError)."\n");
360 outputDist($perOperation);
361 }
362 }
363 my $baseLinePO = $timedata[0]->divideByScalar($iterPerPass[0]*$noopers[0]);
364 for $j ( 1 .. $#timedata ) {
365 my $perOperation = $timedata[$j]->divideByScalar($iterPerPass[$j]*$noopers[$j]); # time per operation
366 my $ratio = $baseLinePO->subtract($perOperation);
367 $ratio = $ratio->divide($perOperation);
368 outputDist($ratio, "%");
369 }
370 if (@noevents) {
371 for $j ( 0 .. $#timedata ) {
372 #outputData($noevents[$j], "RIGHT");
373 outputValue($noevents[$j]);
374 }
375 for $j ( 0 .. $#timedata ) {
376 my $perEvent = $timedata[$j]->divideByScalar($iterPerPass[$j]*$noevents[$j]); # time per event
377 #debug("Time per operation: ".formatSeconds(4, $perEvent->getMean, $perEvent->getError)."\n");
378 outputDist($perEvent);
379 }
380 my $baseLinePO = $timedata[0]->divideByScalar($iterPerPass[0]*$noevents[0]);
381 for $j ( 1 .. $#timedata ) {
382 my $perOperation = $timedata[$j]->divideByScalar($iterPerPass[$j]*$noevents[$j]); # time per operation
383 my $ratio = $baseLinePO->subtract($perOperation);
384 $ratio = $ratio->divide($perOperation);
385 outputDist($ratio, "%");
386 }
387 }
388 }
389
390
391 1;
392
393 #eof