1#!/usr/bin/perl
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26# ident	"%Z%%M%	%I%	%E% SMI"
27#
28
29#
30# Compare filebench results
31#
32# Usage: filebench_summary <dir1> <dir2> ...
33#
34
35use CGI ':standard';
36
37$maxiopsoverall = 0;
38$maxiopsrate = 0;
39$maxbandwidth = 0;
40
41#
42# Create html and text
43#
44open (HTML, ">index.html");
45print HTML start_html(-title=>'Filebench');
46print HTML "<body>";
47#
48# Print aggregate flowop stats
49#
50foreach $dir (@ARGV) {
51
52    printf ("Generating html for $dir\n");
53    open (PROFILE, "<$dir/thisrun.prof");
54    $description = <PROFILE>;
55    $description =~ s/.*"(.+)".*/$1/;
56
57    $files = `ls $dir/stats.*.out $dir/*/stats.*.out 2>/dev/null`;
58    foreach $file (split(/\n/, $files)) {
59	print "file = $file\n";
60
61	# Search backwards in-case the hostname is of FQDN or there's a
62	# '.' in $dir.
63	$rstr = reverse $file;
64	($rfstype, $rworkload, $rprefix) = split(/\./, $rstr);
65	$prefix = reverse $rprefix;
66	$workload = reverse $rworkload;
67	$fstype = reverse $rfstype;
68
69	$dataset = $dir;
70	$dataset =~ s/.*\/(.+)$/$1/;
71	$dataset =~ s/\/$//;
72        $desc{$dataset} = "$description";
73
74	open (STATS, $file);
75	$tmp = <STATS>;
76	while (<STATS>) {
77	    ($flowop, $ops, $bandwidth, $latency, $cpu, $wait, $seconds) = split(/[ \t]+/, $_);
78
79	    if (/^$/) {
80		$tmp = <STATS>;
81	        ($fluff, $opcnt, $ops, $reads, $writes, $bandwidth,
82		    $cpu) = split(/[ \tA-z:\/,]+/, $tmp);
83	        $ops{$workload, $dataset} = $ops;
84	  	last;
85	    }
86
87	    $ops =~ s/ops\/s//;
88	    $bandwidth =~ s/mb\/s//;
89	    $latency =~ s/ms\/op//;
90	    $cpu =~ s/us\/op//;
91
92	    # Collapse shadow reads into single metric
93	    if ($flowop =~ /shadowread/) {
94		$flowop = "shadow-read";
95	    }
96
97	    # Collapse database writes into single metric
98	    if ($flowop =~ /db.*write/) {
99		$flowop = "db-write";
100	    }
101
102	    # Collapse database writes into single metric
103	    if ($flowop =~ /db.*write/) {
104		$flowop = "db-write";
105	    }
106
107	    $datasets{$dataset} = $dataset;
108	    $workloads{$workload} = $workload;
109
110	    $flowops{$flowop} = $flowop;
111	    $wkl_flowops{$flowop, $workload} = $flowop;
112	    $wkl_workload{$flowop, $workload} = $workload;
113	    $flow_ops{$flowop, $workload, $dataset} += $ops;
114	    $flow_bandwidth{$flowop, $workload, $dataset} += $bandwidth;
115	    $flow_latency{$flowop, $workload, $dataset} += $latency;
116	    $flow_cpu{$flowop, $workload, $dataset} += $cpu;
117
118	    $bandwidth{$workload, $dataset} += $bandwidth;
119	    $latency{$workload, $dataset} += $latency;
120	    $cpu{$workload, $dataset} += $cpu;
121
122	    $flowopcnt{$flowop, $workload, $dataset}++;
123	    $workloadcnt{$workload, $dataset}++;
124	}
125	close(STATS);
126    }
127}
128
129# HTML IOPS
130print HTML h1('Throughput breakdown (ops per second)');
131print HTML "<table border=1>";
132print HTML "<b><td>Workload</td>";
133foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
134    print HTML "<td>$desc{$dataset}</td>";
135}
136print HTML "</b></tr>";
137
138foreach $workload (sort (keys %workloads)) {
139    print HTML "<b><tr><td>$workload</td>";
140    $last = 0;
141    foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
142	$color = "white";
143        $this = $ops{$workload, $dataset};
144        if ($last && ($this - $last) < ($last * -0.1)) {
145		$color = "red";
146        }
147        if ($last && ($this - $last) > ($last * 0.1)) {
148		$color = "green";
149	}
150	printf HTML ("<td>%d</td\n", $this);
151	$last = $ops{$workload, $dataset};
152    }
153    print HTML "</b></tr>";
154}
155print HTML "</table>";
156
157# HTML Bandwidth
158print HTML h1('Bandwidth breakdown (MB/s)');
159print HTML "<table border=1>";
160print HTML "<td>Workload</td>";
161foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
162    print HTML "<td>$desc{$dataset}</td>";
163}
164print HTML "</tr>";
165foreach $workload (sort (keys %workloads)) {
166    $bandwidth = 0;
167    foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
168	$bandwidth +=  $bandwidth{$workload, $dataset};
169    }
170    next if ($bandwidth == 0);
171    print HTML "<tr><td>$workload</td>";
172    foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
173	printf HTML ("<td>%d</td>\n", $bandwidth{$workload, $dataset});
174    }
175    print HTML "</tr>";
176}
177print HTML "</table>";
178
179# HTML Latency
180print HTML h1('Latency breakdown (ms per op)');
181print HTML "<table border=1>";
182print HTML "<td>Workload</td>";
183foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
184    print HTML "<td>$desc{$dataset}</td>";
185}
186
187print HTML "</tr>";
188foreach $workload (sort (keys %workloads)) {
189    print HTML "<tr><td>$workload</td>";
190    foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
191	if ( $workloadcnt{$workload, $dataset}) {
192	    printf HTML ("<td>%.1f</td>", $latency{$workload,
193		$dataset} / $workloadcnt{$workload, $dataset});
194        } else {
195             printf HTML ("<td></td>");
196        }
197    }
198    print HTML "</tr>";
199    foreach $flowop (keys %wkl_flowops) {
200        next if ("$wkl_workload{$flowop}" ne "$workload");
201        print HTML "<tr><td><i>__$wkl_flowops{$flowop}</td>";
202        foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
203	     if ( $flowopcnt{$flowop, $dataset}) {
204	         printf HTML ("<td>%.1f</td>\n", $flow_latency{$flowop,
205		    $dataset} / $flowopcnt{$flowop, $dataset});
206             } else {
207	         printf HTML ("<td></td>");
208             }
209        }
210        print HTML "</i></tr>";
211    }
212}
213print HTML "</table>";
214
215# HTML Efficiency
216print HTML h1('Efficiency breakdown (Code path length in uS/op)');
217print HTML "<table border=1>";
218print HTML "<td>Workload</td>";
219foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
220    print HTML "<td>$desc{$dataset}</td>";
221}
222print HTML "</tr>";
223foreach $workload (sort (keys %workloads)) {
224    print HTML "<tr><td>$workload</td>";
225    foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
226	if ($workloadcnt{$workload, $dataset}) {
227	    printf HTML ("<td>%d</td>", $cpu{$workload, $dataset}
228		/ $workloadcnt{$workload, $dataset});
229        } else {
230             printf HTML ("<td></td>");
231        }
232    }
233    print HTML "</tr>";
234    foreach $flowop (keys %wkl_flowops) {
235        next if ("$wkl_workload{$flowop}" ne "$workload");
236        print HTML "<tr><td><i>__$wkl_flowops{$flowop}</td>";
237        foreach $dataset (sort {$a cmp $b}(keys %datasets)) {
238	    if ($flowopcnt{$flowop, $dataset}) {
239	        printf HTML ("<td>%d</td>\n", $flow_cpu{$flowop,
240		    $dataset} / $flowopcnt{$flowop, $dataset});
241            } else {
242                 printf HTML ("<td></td>");
243            }
244        }
245        print HTML "</i></tr>";
246    }
247}
248print HTML "</table>";
249
250end_html();
251