
# Generate an ascii summary from lmbench result files.
# Usage: getsummary file file file...
#
# Hacked into existence by Larry McVoy (lm@sun.com now lm@sgi.com).
# Copyright (c) 1994 Larry McVoy.  GPLed software.
# $Id: getsummary,v 1.1 1994/11/23 07:16:48 lm Exp $
eval "exec perl -Ss $0 $*"
	if 0;

foreach $file (@ARGV) {
	push(@files, $file);
	open(FD, $file) || die "$0: can't open $file";
	$file =~ s|.*/||;
	push(@file, $file);
	while (<FD>) {
		chop;
		if (/^\[lmbench/) {
			split;
			push(@uname, "@_");
		}
		if (/Mhz/) {
			split;
			push(@misc_mhz, $_[0]);
		}
		if (/^Null syscall:/) {
			split;
			push(@lat_nullsys, $_[2]);
		}
		if (/^Pipe latency:/) {
			split;
			push(@lat_pipe, $_[2]);
		}
		if (/UDP latency using localhost:/) {
			split;
			push(@lat_udp_local, $_[4]);
		}
		if (/TCP latency using localhost/) {
			split;
			push(@lat_tcp_local, $_[4]);
		}
		if (/RPC.udp latency using localhost/) {
			split;
			push(@lat_rpc_udp_local, $_[4]);
		}
		if (/RPC.tcp latency using localhost/) {
			split;
			push(@lat_rpc_tcp_local, $_[4]);
		}
		if (/^Process fork.exit/) {
			split;
			push(@lat_nullproc, $_[2]);
		}
		if (/^Process fork.execve/) {
			split;
			push(@lat_simpleproc, $_[2]);
		}
		if (/^Process fork..bin.sh/) {
			split;
			push(@lat_shproc, $_[3]);
		}
		if (/size=0 ovr=/) {
			while (<FD>) {
				next unless /^2/;
				split;
				push(@lat_ctx, $_[1]);
			    	last;
			}
			while (<FD>) {
				next unless /^8/;
				split;
				push(@lat_ctx8, $_[1]);
			    	last;
			}
		}
		if (/^Pipe bandwidth/) {
			split;
			push(@bw_pipe, $_[2]);
		}
		if (/^Socket bandwidth using localhost/) {
			split;
			push(@bw_tcp_local, $_[4]);
		}
		if (/^File .* write bandwidth/) {
			split;
			$bw = sprintf("%.2f", $_[4] / 1024.);
			push(@bw_file, $bw);
		}
		if (/^"mappings/) {
			$done = 0;
			while (<FD>) {
				last if /^\s*$/;
				$save = $_ if /^\d\./;
				next unless /^8.00/;
				split;
				push(@lat_mappings, $_[1]);
				$done++;
			    	last;
			}
			unless ($done) {
				$_ = $save;
				split;
				push(@lat_mappings, $_[1]);
				warn "$file: No 8MB found for " .
				    "memory mapping timing, using $_[0]\n";
			}
		}
		if (/^"read bandwidth/) {
			$done = 0;
			while (<FD>) {
				last if /^\s*$/;
				$save = $_ if /^\d\./;
				next unless /^8.00/;
				split;
				push(@bw_reread, $_[1]);
				$done++;
			    	last;
			}
			unless ($done) {
				$_ = $save;
				split;
				push(@bw_reread, $_[1]);
				warn "$file: No 8MB found for " .
				    "reread timing, using $_[0]\n";
			}
		}
		if (/^"Mmap read bandwidth/) {
			$done = 0;
			while (<FD>) {
				last if /^\s*$/;
				$save = $_ if /^\d\./;
				next unless /^8.00/;
				split;
				push(@bw_mmap, $_[1]);
				$done++;
			    	last;
			}
			unless ($done) {
				$_ = $save;
				split;
				push(@bw_mmap, $_[1]);
				warn "$file: No 8MB found for " .
				    "mmap reread timing, using $_[0]\n";
			}
		}
		if (/^"libc bcopy unaligned/) {
			while (<FD>) {
				next unless /^8.00/;
				split;
				push(@bw_bcopy_libc, $_[1]);
			    	last;
			}
		}
		if (/^"unrolled bcopy unaligned/) {
			while (<FD>) {
				next unless /^8.00/;
				split;
				push(@bw_bcopy_unrolled, $_[1]);
			    	last;
			}
		}
		if (/^Memory read/) {
			while (<FD>) {
				next unless /^8.00/;
				split;
				push(@bw_mem_rdsum, $_[1]);
			    	last;
			}
		}
		if (/^Memory write/) {
			while (<FD>) {
				next unless /^8.00/;
				split;
				push(@bw_mem_wr, $_[1]);
			    	last;
			}
		}
		if (/^"stride=128/) {
			while (<FD>) {
				if (/^0.00098\s/) {
					split;
					push(@lat_l1, $_[1]);
				} elsif (/^0.12500\s/) {
					split;
					push(@lat_l2, $_[1]);
				} elsif (/^8.00000\s/) {
					split;
					push(@lat_mem, $_[1]);
					last;
				}
			}
		}
		if (/^"stride=8192/) {	# XXX assumes <= 8K pagesize
			$tbl = -1;
			while (<FD>) {
				if (/^8.00000\s/) {
					split;
					$tlb = $_[1];
				}
			}
			push(@lat_tlb, $tlb);
		}
	}
	foreach $array ('lat_tlb', 'lat_mem', 'lat_l1', 'lat_l2') {
		eval "if (\$#$array != $i) {
			warn \"No data for $array in $file\n\";
			push(\@$array, -1);
		    }";
	}
	$i++;
}


print<<EOF;

                    L M B E N C H  1 . 0   S U M M A R Y
                    ------------------------------------

            Processor, Processes - times in microseconds
            --------------------------------------------
Host                 OS  Mhz    Null    Null  Simple /bin/sh Mmap 2-proc 8-proc
                             Syscall Process Process Process  lat  ctxsw  ctxsw
--------- ------------- ---- ------- ------- ------- ------- ---- ------ ------
EOF

for ($i = 0; $i <= $#uname; $i++) {
        printf "%-9.9s %13.13s ", $file[$i], &getos($uname[$i]);
            printf "%4.0f %7d %6.1fK %6.1fK %6.0fK %4d %6d %6d\n",
            $misc_mhz[$i],
            $lat_nullsys[$i],
            $lat_nullproc[$i]/1000.,
            $lat_simpleproc[$i]/1000.,
            $lat_shproc[$i]/1000.,
            $lat_mappings[$i],
            $lat_ctx[$i],
            $lat_ctx8[$i];

}

print<<EOF;

            *Local* Communication latencies in microseconds
            -----------------------------------------------
Host                 OS  Pipe       UDP    RPC/     TCP    RPC/
                                            UDP             TCP
--------- ------------- ------- ------- ------- ------- -------
EOF

for ($i = 0; $i <= $#uname; $i++) {
        printf "%-9.9s %13.13s ", $file[$i], &getos($uname[$i]);
        printf "%7d %7d %7d %7d %7d\n",
            $lat_pipe[$i],
            $lat_udp_local[$i],
            $lat_rpc_udp_local[$i],
            $lat_tcp_local[$i],
            $lat_rpc_tcp_local[$i];

}

print<<EOF;

            *Local* Communication bandwidths in megabytes/second
            ----------------------------------------------------
Host                 OS Pipe  TCP  File   Mmap  Bcopy  Bcopy  Mem   Mem
                                  reread reread (libc) (hand) read write
--------- ------------- ---- ---- ------ ------ ------ ------ ---- -----
EOF

for ($i = 0; $i <= $#uname; $i++) {
        printf "%-9.9s %13.13s ", $file[$i], &getos($uname[$i]);
        printf "%4.0f %4.1f %6.1f %6.1f %6.0f %6.0f %4.0f %5.0f\n",
            $bw_pipe[$i], $bw_tcp_local[$i], 
            $bw_reread[$i], $bw_mmap[$i], $bw_bcopy_libc[$i],
            $bw_bcopy_unrolled[$i],
            $bw_mem_rdsum[$i],
            $bw_mem_wr[$i];
}

print<<EOF;

	    Memory latencies in nanoseconds
            (WARNING - may not be correct, check graphs)
            --------------------------------------------
Host                 OS   Mhz  L1 \$   L2 \$    Main mem    TLB    Guesses
--------- -------------   ---  ----   ----    --------    ---    -------
EOF

for ($i = 0; $i <= $#uname; $i++) {
        printf "%-9.9s %13.13s   %3d",
	    $file[$i], &getos($uname[$i]), $misc_mhz[$i];
	$msg = &check_caches;
	if ($lat_l1[$i] <= 1) {
        	printf "%6s %6s %11s %6s    %s",
		    "-", "-", "-", "-",
		    "Bad mhz?";
	} else {
		printf "%6.0f %6.0f %11.0f %6.0f",
		    $lat_l1[$i], $lat_l2[$i], 
		    $lat_mem[$i], $lat_tlb[$i];
		print $msg if ($msg =~ /L/);
	}
	print "\n";
}

exit 0;


# Try and create sensible names from uname -a output
sub getos
{
        local(@info);

        @info = split(/\s+/, $_[0]);
        "$info[3] $info[5]";
}

# Return true if the values differe by less than 10%
sub same
{
	local($a, $b) = @_;

	if ($a > $b) {
		$percent = (($a - $b) / $a) * 100;
	} else {
		$percent = (($b - $a) / $b) * 100;
	}
	return ($percent <= 20);
}

sub check_caches
{
	if (!&same($lat_l1[$i], $lat_l2[$i]) &&
	    &same($lat_l2[$i], $lat_mem[$i])) {
		"    No L2 cache?";
	} elsif (&same($lat_l1[$i], $lat_l2[$i])) {
		"    No L1 cache?";
	}
}
