3 use lib
'../../perl/build/lib';
12 open my $fh, "<", $name or return undef;
14 return undef if not defined $line;
15 close $fh or die "cannot close $name: $!";
16 $line =~ /^(?:(\d+):)?(\d+):(\d+(?:\.\d+)?) (\d+(?:\.\d+)?) (\d+(?:\.\d+)?)$/
17 or die "bad input line: $line";
18 my $rt = ((defined $1 ?
$1 : 0.0)*60+$2)*60+$3;
23 my ($r, $u, $s, $firstr) = @_;
27 my $out = sprintf "%.2f(%.2f+%.2f)", $r, $u, $s;
28 if (defined $firstr) {
30 $out .= sprintf " %+.1f%%", 100.0*($r-$firstr)/$firstr;
42 ./aggregate.perl [options] [--] [<dir_or_rev>...] [--] [<test_script>...] >
45 --codespeed * Format output for Codespeed
46 --reponame <str> * Send given reponame to codespeed
47 --sort-by <str> * Sort output (only "regression" criteria is supported)
48 --subsection <str> * Use results from given subsection
54 my (@dirs, %dirnames, %dirabbrevs, %prefixes, @tests,
55 $codespeed, $sortby, $subsection, $reponame);
57 Getopt
::Long
::Configure qw
/ require_order /;
59 my $rc = GetOptions
("codespeed" => \
$codespeed,
60 "reponame=s" => \
$reponame,
61 "sort-by=s" => \
$sortby,
62 "subsection=s" => \
$subsection);
65 while (scalar @ARGV) {
68 last if -f
$arg or $arg eq "--";
70 my $rev = Git
::command_oneline
(qw(rev-parse --verify), $arg);
75 $dirabbrevs{$dir} = $dir;
78 $dirnames{$dir} = $arg;
80 $prefix =~ tr/^a-zA-Z0-9/_/c;
81 $prefixes{$dir} = $prefix . '.';
88 $dirnames{'.'} = $dirabbrevs{'.'} = "this tree";
91 shift @ARGV if scalar @ARGV and $ARGV[0] eq "--";
95 @tests = glob "p????-*.sh";
98 my $resultsdir = "test-results";
100 if (! $subsection and
101 exists $ENV{GIT_PERF_SUBSECTION
} and
102 $ENV{GIT_PERF_SUBSECTION
} ne "") {
103 $subsection = $ENV{GIT_PERF_SUBSECTION
};
107 $resultsdir .= "/" . $subsection;
113 $t =~ s{(?:.*/)?(p(\d+)-[^/]+)\.sh$}{$1} or die "bad test name: $t";
115 my $fname = "$resultsdir/$t.subtests";
116 open my $fp, "<", $fname or die "cannot open $fname: $!";
119 /^(\d+)$/ or die "malformed subtest line: $_";
120 push @subtests, "$t.$1";
121 $shorttests{"$t.$1"} = "$n.$1";
123 close $fp or die "cannot close $fname: $!";
128 open my $fh, "<", $name or return "<error reading description>";
129 binmode $fh, ":utf8" or die "PANIC on binmode: $!";
131 close $fh or die "cannot close $name";
139 return 1 if exists $seen{$_};
153 return exists $dirabbrevs{$d} ?
$dirabbrevs{$d} : $dirnames{$d};
156 sub print_default_results
{
158 my $descrlen = 4; # "Test"
159 for my $t (@subtests) {
160 $descrs{$t} = $shorttests{$t}.": ".read_descr
("$resultsdir/$t.descr");
161 $descrlen = length $descrs{$t} if length $descrs{$t}>$descrlen;
164 my %newdirabbrevs = %dirabbrevs;
165 while (!have_duplicate
(values %newdirabbrevs)) {
166 %dirabbrevs = %newdirabbrevs;
167 last if !have_slash
(values %dirabbrevs);
168 %newdirabbrevs = %dirabbrevs;
169 for (values %newdirabbrevs) {
175 my @colwidth = ((0)x
@dirs);
176 for my $i (0..$#dirs) {
177 my $w = length display_dir
($dirs[$i]);
178 $colwidth[$i] = $w if $w > $colwidth[$i];
180 for my $t (@subtests) {
182 for my $i (0..$#dirs) {
184 $times{$prefixes{$d}.$t} = [get_times
("$resultsdir/$prefixes{$d}$t.times")];
185 my ($r,$u,$s) = @
{$times{$prefixes{$d}.$t}};
186 my $w = length format_times
($r,$u,$s,$firstr);
187 $colwidth[$i] = $w if $w > $colwidth[$i];
188 $firstr = $r unless defined $firstr;
191 my $totalwidth = 3*@dirs+$descrlen;
192 $totalwidth += $_ for (@colwidth);
194 printf "%-${descrlen}s", "Test";
195 for my $i (0..$#dirs) {
196 printf " %-$colwidth[$i]s", display_dir
($dirs[$i]);
199 print "-"x
$totalwidth, "\n";
200 for my $t (@subtests) {
201 printf "%-${descrlen}s", $descrs{$t};
203 for my $i (0..$#dirs) {
205 my ($r,$u,$s) = @
{$times{$prefixes{$d}.$t}};
206 printf " %-$colwidth[$i]s", format_times
($r,$u,$s,$firstr);
207 $firstr = $r unless defined $firstr;
213 sub print_sorted_results
{
216 if ($sortby ne "regression") {
217 print "Only 'regression' is supported as '--sort-by' argument\n";
222 for my $t (@subtests) {
223 my ($prevr, $prevu, $prevs, $prevrev);
224 for my $i (0..$#dirs) {
226 my ($r, $u, $s) = get_times
("$resultsdir/$prefixes{$d}$t.times");
227 if ($i > 0 and defined $r and defined $prevr and $prevr > 0) {
228 my $percent = 100.0 * ($r - $prevr) / $prevr;
229 push @evolutions, { "percent" => $percent,
231 "prevrev" => $prevrev,
240 ($prevr, $prevu, $prevs, $prevrev) = ($r, $u, $s, $d);
244 my @sorted_evolutions = sort { $b->{percent
} <=> $a->{percent
} } @evolutions;
246 for my $e (@sorted_evolutions) {
247 printf "%+.1f%%", $e->{percent
};
248 print " " . $e->{test
};
249 print " " . format_times
($e->{prevr
}, $e->{prevu
}, $e->{prevs
});
250 print " " . format_times
($e->{r
}, $e->{u
}, $e->{s
});
251 print " " . display_dir
($e->{prevrev
});
252 print " " . display_dir
($e->{rev
});
257 sub print_codespeed_results
{
258 my ($subsection) = @_;
262 my $executable = `uname -s -m`;
266 $executable .= ", " . $subsection;
271 $environment = $reponame;
272 } elsif (exists $ENV{GIT_PERF_REPO_NAME
} and $ENV{GIT_PERF_REPO_NAME
} ne "") {
273 $environment = $ENV{GIT_PERF_REPO_NAME
};
274 } elsif (exists $ENV{GIT_TEST_INSTALLED
} and $ENV{GIT_TEST_INSTALLED
} ne "") {
275 $environment = $ENV{GIT_TEST_INSTALLED
};
276 $environment =~ s
|/bin
-wrappers
$||;
278 $environment = `uname -r`;
284 for my $t (@subtests) {
286 my $commitid = $prefixes{$d};
287 $commitid =~ s/^build_//;
288 $commitid =~ s/\.$//;
289 my ($result_value, $u, $s) = get_times
("$resultsdir/$prefixes{$d}$t.times");
292 "commitid" => $commitid,
293 "project" => $project,
294 "branch" => $dirnames{$d},
295 "executable" => $executable,
296 "benchmark" => $shorttests{$t} . " " . read_descr
("$resultsdir/$t.descr"),
297 "environment" => $environment,
298 "result_value" => $result_value,
304 print to_json
(\
@data, {utf8
=> 1, pretty
=> 1, canonical
=> 1}), "\n";
307 binmode STDOUT
, ":utf8" or die "PANIC on binmode: $!";
310 print_codespeed_results
($subsection);
311 } elsif (defined $sortby) {
312 print_sorted_results
($sortby);
314 print_default_results
();