# 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$ eval 'exec perl -Ssw $0 "$@"' if 0; # Use these constants to same typo-induced bugs later! $M = 1000000.; $K = 1000.; $n = 0; foreach $file (@ARGV) { open(FD, $file) || die "$0: can't open $file"; $file =~ s/\.\d+$//; @_ = split(/\//, $file); push(@host, $_[$#_]); $file = $_[$#_ - 1]; $file =~ s|/|-|; push(@file, $file); $lat_mem_rd_type = -1; $mhz = 0; while () { chop; next if m|scripts/lmbench: /dev/tty|; if (/^\[lmbench/) { $version = -1; push(@uname, $_); if (/lmbench1\./) { $version = 1; } if (/lmbench2\./) { $version = 2; } if (/lmbench3\./) { $version = 3; } } if (/MHZ/ && !$mhz) { @_ = split; $_[1] =~ s/\]//; push(@misc_mhz, $_[1]); $mhz = 1; } elsif (/Mhz/ && !$mhz) { @_ = split; push(@misc_mhz, $_[0]); $mhz = 1; } if (/^Select on 100 fd/) { @_ = split; push(@lat_fd_select, $_[4]); } if (/^Select on 100 tcp fd/) { @_ = split; push(@lat_tcp_select, $_[5]); } if (/^integer bit:/) { @_ = split; push(@integer_bit, $_[2]); } if (/^integer add:/) { @_ = split; push(@integer_add, $_[2]); } if (/^integer mul:/) { @_ = split; push(@integer_mul, $_[2]); } if (/^integer div:/) { @_ = split; push(@integer_div, $_[2]); } if (/^integer mod:/) { @_ = split; push(@integer_mod, $_[2]); } if (/^int64 bit:/) { @_ = split; push(@int64_bit, $_[2]); } if (/^int64 add:/) { @_ = split; push(@int64_add, $_[2]); } if (/^int64 mul:/) { @_ = split; push(@int64_mul, $_[2]); } if (/^int64 div:/) { @_ = split; push(@int64_div, $_[2]); } if (/^int64 mod:/) { @_ = split; push(@int64_mod, $_[2]); } if (/^float add:/) { @_ = split; push(@float_add, $_[2]); } if (/^float mul:/) { @_ = split; push(@float_mul, $_[2]); } if (/^float div:/) { @_ = split; push(@float_div, $_[2]); } if (/^double add:/) { @_ = split; push(@double_add, $_[2]); } if (/^double mul:/) { @_ = split; push(@double_mul, $_[2]); } if (/^double div:/) { @_ = split; push(@double_div, $_[2]); } if (/^float bogomflops:/) { @_ = split; push(@float_bogomflops, $_[2]); } if (/^double bogomflops:/) { @_ = split; push(@double_bogomflops, $_[2]); } if (/LINE_SIZE/) { @_ = split; $_[1] =~ s/\]//; push(@line_size, $_[1]); } if (/SYNC_MAX/) { @_ = split; $_[1] =~ s/\]//; push(@load, $_[1]); } if (/^tlb:/) { @_ = split; push(@tlb, $_[1]); } if (/^Simple syscall:/) { @_ = split; push(@lat_syscall, $_[2]); } if (/^Simple read:/) { @_ = split; push(@lat_read, $_[2]); } if (/^Simple write:/) { @_ = split; push(@lat_write, $_[2]); } if (/^Simple stat:/) { @_ = split; push(@lat_stat, $_[2]); } if (/^Simple open.close:/) { @_ = split; push(@lat_openclose, $_[2]); } if (/^Null syscall:/) { # Old format. @_ = split; push(@lat_write, $_[2]); } if (/^Signal handler installation:/) { @_ = split; push(@lat_siginstall, $_[3]); } if (/^Signal handler overhead:/) { @_ = split; push(@lat_sigcatch, $_[3]); } if (/^Protection fault:/) { @_ = split; push(@lat_protfault, $_[2]); } if (/^Pipe latency:/) { @_ = split; push(@lat_pipe, $_[2]); } if (/AF_UNIX sock stream latency:/) { @_ = split; push(@lat_unix, $_[4]); } if (/UDP latency using localhost:/) { @_ = split; push(@lat_udp_local, $_[4]); } elsif (/UDP latency using/) { @_ = split; push(@lat_udp_remote, $_[4]); } if (/TCP latency using localhost:/) { @_ = split; push(@lat_tcp_local, $_[4]); } elsif (/TCP latency using/) { @_ = split; push(@lat_tcp_remote, $_[4]); } if (/RPC.udp latency using localhost:/) { @_ = split; push(@lat_rpc_udp_local, $_[4]); } elsif (/RPC.udp latency using/) { @_ = split; push(@lat_rpc_udp_remote, $_[4]); } if (/RPC.tcp latency using localhost:/) { @_ = split; push(@lat_rpc_tcp_local, $_[4]); } elsif (/RPC.tcp latency using/) { @_ = split; push(@lat_rpc_tcp_remote, $_[4]); } if (/TCP.IP connection cost to localhost:/) { @_ = split; push(@lat_tcp_connect_local, $_[5]); } elsif (/TCP.IP connection cost to/) { @_ = split; push(@lat_tcp_connect_remote, $_[5]); } if (/^Socket bandwidth using localhost/) { $value = &getbiggest("Socket bandwidth using localhost"); push(@bw_tcp_local, $value); # } elsif (/^Socket bandwidth using /) { # $value = &getbiggest("Socket bandwidth using remote"); # push(@bw_tcp_remote, $value); } if (/^AF_UNIX sock stream bandwidth:/) { @_ = split; push(@bw_unix, $_[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 (/^Pipe bandwidth/) { @_ = split; push(@bw_pipe, $_[2]); } if (/^File .* write bandwidth/) { @_ = split; $bw = sprintf("%.2f", $_[4] / 1024.); push(@bw_file, $bw); } if (/^Pagefaults on/) { @_ = split; push(@lat_pagefault, $_[3]); } if (/^"mappings/) { $value = &getbiggest("memory mapping timing"); push(@lat_mappings, $value); } if (/^"read bandwidth/) { $value = &getbiggest("reread timing"); push(@bw_reread, $value); } if (/^"Mmap read bandwidth/) { $value = &getbiggest("mmap reread timing"); push(@bw_mmap, $value); } if (/^"libc bcopy unaligned/) { $value = &getbiggest("libc bcopy timing"); push(@bw_bcopy_libc, $value); } if (/^"unrolled bcopy unaligned/) { $value = &getbiggest("unrolled bcopy timing"); push(@bw_bcopy_unrolled, $value); } if (/^Memory read/) { $value = &getbiggest("memory read & sum timing"); push(@bw_mem_rdsum, $value); } if (/^Memory write/) { $value = &getbiggest("memory write timing"); push(@bw_mem_wr, $value); } if (/^Memory load parallelism/) { $value = &getbiggest("Memory load parallelism"); push(@mem_load_par, $value); } if (/^"File system latency/) { while () { next if /Id:/; if (/^0k/) { @_ = split; push(@fs_create_0k, $_[2]); push(@fs_delete_0k, $_[3]); } elsif (/^1k/) { @_ = split; push(@fs_create_1k, $_[2]); push(@fs_delete_1k, $_[3]); } elsif (/^4k/) { @_ = split; push(@fs_create_4k, $_[2]); push(@fs_delete_4k, $_[3]); } elsif (/^10k/) { @_ = split; push(@fs_create_10k, $_[2]); push(@fs_delete_10k, $_[3]); } else { last; } } } if (/size=0/) { while () { if (/^2 /) { @_ = split; push(@lat_ctx0_2, $_[1]); } elsif (/^8 /) { @_ = split; push(@lat_ctx0_8, $_[1]); } elsif (/^16 /) { @_ = split; push(@lat_ctx0_16, $_[1]); } last if /^\s*$/ || /^Memory/; } } if (/size=16/) { while () { if (/^2 /) { @_ = split; push(@lat_ctx16_2, $_[1]); } elsif (/^8 /) { @_ = split; push(@lat_ctx16_8, $_[1]); } elsif (/^16 /) { @_ = split; push(@lat_ctx16_16, $_[1]); } last if /^\s*$/; } } if (/size=64/) { while () { if (/^2 /) { @_ = split; push(@lat_ctx64_2, $_[1]); } elsif (/^8 /) { @_ = split; push(@lat_ctx64_8, $_[1]); } elsif (/^16 /) { @_ = split; push(@lat_ctx64_16, $_[1]); } last if /^\s*$/ || /^20/; } } if (/^Memory load latency/) { $lat_mem_rd_type = 1; } if (/^Random load latency/) { $lat_mem_rd_type = 2; } if (/^"stride=128/) { $save = -1; while () { if (/^\s*$/) { last; } @_ = split; $size = $_[0]; $save = $_[1]; if ($size == 0.00098 && $lat_mem_rd_type == 1) { push(@lat_l1, $_[1]); } elsif ($size == 0.12500 && $lat_mem_rd_type == 1) { push(@lat_l2, $_[1]); } } if ($size < 8.0) { warn "$file: No 8MB memory latency, using $size\n"; } if ($lat_mem_rd_type == 1) { push(@lat_mem, $save); } } if (/^"stride=16/) { $save = -1; while () { if (/^\s*$/) { last; } @_ = split; $size = $_[0]; $save = $_[1]; } if ($size < 8.0) { warn "$file: No 8MB random access memory latency, using $size\n"; } if ($lat_mem_rd_type == 2) { #warn "$file: lat_mem_rand = $save\n"; push(@lat_mem_rand, $save); } } } @warn = (); foreach $array ( 'bw_bcopy_libc', 'bw_bcopy_unrolled', 'bw_file', 'bw_mem_rdsum', 'bw_mem_wr', 'bw_mmap', 'bw_pipe', 'bw_reread', 'bw_tcp_local', 'bw_tcp_remote', 'bw_unix', 'double_add', 'double_bogomflops', 'double_div', 'double_mul', 'float_add', 'float_bogomflops', 'float_div', 'float_mul', 'fs_create_0k', 'fs_create_1k', 'fs_create_4k', 'fs_create_10k', 'fs_delete_0k', 'fs_delete_1k', 'fs_delete_4k', 'fs_delete_10k', 'integer_add', 'integer_bit', 'integer_div', 'integer_mod', 'integer_mul', 'lat_ctx0_2', 'lat_ctx0_8', 'lat_ctx0_16', 'lat_ctx16_2', 'lat_ctx16_8', 'lat_ctx16_16', 'lat_ctx64_2', 'lat_ctx64_8', 'lat_ctx64_16', 'lat_l1', 'lat_l2', 'lat_mappings', 'lat_mem', 'lat_mem_rand', 'lat_nullproc', 'lat_openclose', 'lat_pagefault', 'lat_pipe', 'lat_protfault', 'lat_read', 'lat_rpc_tcp_local', 'lat_rpc_tcp_remote', 'lat_rpc_udp_local', 'lat_rpc_udp_remote', 'lat_fd_select', 'lat_tcp_select', 'lat_shproc', 'lat_sigcatch', 'lat_siginstall', 'lat_simpleproc', 'lat_stat', 'lat_syscall', 'lat_tcp_connect_local', 'lat_tcp_connect_remote', 'lat_tcp_local', 'lat_tcp_remote', 'lat_udp_local', 'lat_udp_remote', 'lat_unix', 'lat_write', 'line_size', 'mem_load_par', 'misc_mhz', 'tlb', 'load', 'int64_add', 'int64_bit', 'int64_div', 'int64_mod', 'int64_mul' ) { $last = eval '$#' . $array; if ($last != $n) { #warn "No data for $array in $file\n"; push(@warn, $array); eval 'push(@' . $array . ', -1);'; } } # if ($#warn != -1) { # warn "Missing data in $file: @warn\n"; # } $n++; } print< 1) { next; } printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]); printf "%6.6s %6.6s %6.6s %6.6s %6.6s\n", &scale_num($integer_bit[$i], 6, $load[$i]), &scale_num($integer_add[$i], 6, $load[$i]), &scale_num($integer_mul[$i], 6, $load[$i]), &scale_num($integer_div[$i], 6, $load[$i]), &scale_num($integer_mod[$i], 6, $load[$i]); } } sub print_uint64 { local($i); local($t); if (&resultsq(0, $#uname, ( 'int64_bit', 'int64_add', 'int64_mul', 'int64_div', 'int64_mod' )) <= 0) { return; } print< 1) { next; } printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]); printf " %5.5s %6.6s %6.6s %6.6s %6.6s\n", &scale_num($int64_bit[$i], 6, $load[$i]), &scale_num($int64_add[$i], 6, $load[$i]), &scale_num($int64_mul[$i], 6, $load[$i]), &scale_num($int64_div[$i], 6, $load[$i]), &scale_num($int64_mod[$i], 6, $load[$i]); } } sub print_float { local($i); local($t); if (&resultsq(0, $#uname, ( 'float_add', 'float_mul', 'float_div', 'float_bogomflops' )) <= 0) { return; } print< 1) { next; } printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]); printf "%6.6s %6.6s %6.6s %6.6s\n", &scale_num($float_add[$i], 6, $load[$i]), &scale_num($float_mul[$i], 6, $load[$i]), &scale_num($float_div[$i], 6, $load[$i]), &scale_num($float_bogomflops[$i], 6, $load[$i]); } } sub print_double { local($i); local($t); if (&resultsq(0, $#uname, ( 'double_add', 'double_mul', 'double_div', 'double_bogomflops' )) <= 0) { return; } print< 1) { next; } printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]); printf "%6.6s %6.6s %6.6s %6.6s\n", &scale_num($double_add[$i], 6, $load[$i]), &scale_num($double_mul[$i], 6, $load[$i]), &scale_num($double_div[$i], 6, $load[$i]), &scale_num($double_bogomflops[$i], 6, $load[$i]); } } sub print_ctx { local($i); local($t); if (&resultsq(0, $#uname, ( 'lat_ctx0_2', 'lat_ctx16_2', 'lat_ctx64_2', 'lat_ctx16_8', 'lat_ctx64_8', 'lat_ctx16_16', 'lat_ctx64_16' )) <= 0) { return; } print< 0) return (1); } } } return (0); } # (33, %3d) sub inum { local($val, $len) = @_; local($str) = ""; local($i); if (!defined($val) || !($val =~ /^[ ]*[0-9.]+[ ]*$/)) { $val = -1; } if ($val <= 0) { $str = ""; for ($i = 0; $i < $len; $i++) { $str .= " "; } return ($str); } $fmt = sprintf("%%%dd", $len); $str = sprintf($fmt, $val); $str; } # (33, %3d, scale) sub scale_num { local($val, $len, $scale) = @_; if ($scale > 1) { $val = -1 } return (&num($val, $len)); } # (33, %3d) sub num { local($val, $len) = @_; local($str) = ""; local($i); if (!defined($val) || !($val =~ /^[ ]*[0-9.]+[ ]*$/)) { $val = -1; } if ($val <= 0) { $str = ""; for ($i = 0; $i < $len; $i++) { $str .= " "; } return ($str); } if ($val >= 10 * $M) { $nstr = sprintf("%.1f", $val / $M); $fmt = sprintf("%%%d.%ds%%s", $len - 1, $len - 1); $str = sprintf($fmt, $nstr, "M"); } elsif ($val >= 10 * $K) { $nstr = sprintf("%.1f", $val / $K); $fmt = sprintf("%%%d.%ds%%s", $len - 1, $len - 1); $str = sprintf($fmt, $nstr, "K"); } elsif ($val >= 10) { $nstr = sprintf("%.1f", $val); $fmt = sprintf("%%%d.%ds", $len, $len); $str = sprintf($fmt, $nstr); } elsif ($val < 0.001) { $fmt = sprintf("%%%d.%de", $len, $len - 6); $str = sprintf($fmt, $val); } else { $fmt = sprintf("%%%d.%df", $len, $len - 2); $str = sprintf($fmt, $val); } $str; } # Input looks like # "benchmark name # size value # .... # # # Return the biggest value before the blank line. sub getbiggest { local($msg) = @_; local($line) = 0; undef $save; $value = 0; while () { $line++; #warn "$line $_"; last if /^\s*$/; last if (!($_ =~ /^\d+/)); $save = $_ if /^\d+\./; } if (defined $save) { $_ = $save; @d = split; $value = $d[1]; if (int($d[0]) < 4) { warn "$file: using $d[0] size for $msg\n"; } } else { warn "$file: no data for $msg\n"; } $value; } # 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?"; } }