1 2# Generate an ascii summary from lmbench result files BY HOSTNAME 3# instead of architecture. Sorry, I think of these tools as being 4# used to measure and prototype particular named systems, not as 5# being useful to measure once and for all "i686-linux" systems, 6# which might well have different motherboards, chipsets, memory 7# clocks, CPU's (anything from PPro through to PIII so far) and 8# so forth. Linux systems are far to heterogeneous to be categorized 9# with two or three descriptors, so might as well just use hostname 10# for shorthand... 11# 12# Usage: statsummary file file file... 13# 14# Hacked into existence by Larry McVoy (lm@sun.com now lm@sgi.com). 15# Copyright (c) 1994 Larry McVoy. GPLed software. 16# 17# $Id: statsummary,v 1.5 2000/07/08 21:06:49 rgb Exp $ 18# 19# 20# Edit History. I'm starting out with Larry's getsummary. Then I'm 21# going to splice in a very simple set of stats routines that are 22# passed an array in his standard form and return a structure containing 23# max, min, mean, median, unbiased standard deviation and we'll go from 24# there. However I'll likely print out only mean and SD and will try 25# to preserve Larry's general layout at that. Oh, and I'm going to add 26# COMMENTS to the script. Drives me nuts to work on something without 27# comments. 7/6/00 28 29eval 'exec perl -Ssw $0 "$@"' 30 if 0; 31 32# 33# This segment loops through all the output files and pushes the 34# specific field values it needs into suitably named arrays. It 35# counts while it does so so it can check to be sure that all 36# the input files are complete. 37$n = 0; 38@hosts = (); 39foreach $file (@ARGV) { 40 open(FD, $file) || die "$0: can't open $file"; 41 # I just want @file to contain the hostname, not the path or architecture. 42 # However, we have reason to need the associated filename (no path) to 43 # to help with debugging. 44 # Strip off the path 45 $file =~ s/(.*)\///; 46 # Split the filename from the number. This will probably break if the 47 # hostname contains more "."'s. However, I'm too lazy to figure out 48 # how to make this work totally robustly. It would be easy if the 49 # the host datafiles were all created according to the "hostname.count" 50 # format, because then a simple regexp would pull off just the hostname 51 # or the count. Not so easy when a hostname/count might contain no "."'s 52 # at all... 53 $filecount = ""; 54 ($file,$filecount) = split(/\./,$file); 55 # fix silly bug caused by starting numbering at blank. 56 if(! $filecount){ 57 $filecount = 0; 58 } 59 # Debugging... 60 # print STDERR "Found file $file with count $filecount\n"; 61 push(@file, $file); 62 push(@filecount, $filecount); 63 64 # This should just push UNIQUE new hosts onto @hosts. 65 $numhosts = @hosts; 66 if($numhosts){ 67 $lasthost = $hosts[$numhosts-1]; 68 } else { 69 $lasthost = ""; 70 } 71 if($lasthost !~ /$file/){ 72 push(@hosts, $file); 73 } 74 75 $mhz = 0; 76 while (<FD>) { 77 chop; 78 next if m|scripts/lmbench: /dev/tty|; 79 if (/^\[lmbench/) { 80 push(@uname, $_); 81 if (/lmbench1\./) { 82 $version = 1; 83 } else { 84 $version = 2; 85 } 86 } 87 if (/MHZ/ && !$mhz) { 88 @_ = split; 89 $_[1] =~ s/\]//; 90 push(@misc_mhz, $_[1]); 91 $mhz = 1; 92 } elsif (/Mhz/ && !$mhz) { 93 @_ = split; 94 push(@misc_mhz, $_[0]); 95 $mhz = 1; 96 } 97 if (/^Select on 100 fd/) { 98 @_ = split; 99 push(@lat_select, $_[4]); 100 $tmp = $lat_select[0]; # Just to shut up the error parser 101 } 102 if (/^Simple syscall:/) { 103 @_ = split; 104 push(@lat_syscall, $_[2]); 105 $tmp = $lat_syscall[0]; # Just to shut up the error parser 106 } 107 if (/^Simple read:/) { 108 @_ = split; 109 push(@lat_read, $_[2]); 110 $tmp = $lat_read[0]; # Just to shut up the error parser 111 } 112 if (/^Simple write:/) { 113 @_ = split; 114 push(@lat_write, $_[2]); 115 $tmp = $lat_write[0]; # Just to shut up the error parser 116 } 117 if (/^Simple stat:/) { 118 @_ = split; 119 push(@lat_stat, $_[2]); 120 $tmp = $lat_stat[0]; # Just to shut up the error parser 121 } 122 if (/^Simple open.close:/) { 123 @_ = split; 124 push(@lat_openclose, $_[2]); 125 $tmp = $lat_openclose[0]; # Just to shut up the error parser 126 } 127 if (/^Null syscall:/) { # Old format. 128 @_ = split; 129 push(@lat_write, $_[2]); 130 $tmp = $lat_write[0]; # Just to shut up the error parser 131 } 132 if (/^Signal handler installation:/) { 133 @_ = split; 134 push(@lat_siginstall, $_[3]); 135 $tmp = $lat_siginstall[0]; # Just to shut up the error parser 136 } 137 if (/^Signal handler overhead:/) { 138 @_ = split; 139 push(@lat_sigcatch, $_[3]); 140 $tmp = $lat_sigcatch[0]; # Just to shut up the error parser 141 } 142 if (/^Protection fault:/) { 143 @_ = split; 144 push(@lat_protfault, $_[2]); 145 $tmp = $lat_protfault[0]; # Just to shut up the error parser 146 } 147 if (/^Pipe latency:/) { 148 @_ = split; 149 push(@lat_pipe, $_[2]); 150 $tmp = $lat_pipe[0]; # Just to shut up the error parser 151 } 152 if (/AF_UNIX sock stream latency:/) { 153 @_ = split; 154 push(@lat_unix, $_[4]); 155 $tmp = $lat_unix[0]; # Just to shut up the error parser 156 } 157 if (/^UDP latency using /) { 158 if(/localhost:/) { 159 @_ = split; 160 push(@lat_udp_local, $_[4]); 161 $tmp = $lat_udp_local[0]; # Just to shut up the error parser 162 } else { 163 @_ = split; 164 push(@lat_udp_net, $_[4]); 165 $tmp = $lat_udp_net[0]; # Just to shut up the error parser 166 } 167 } 168 if (/^TCP latency using /) { 169 if(/localhost:/) { 170 @_ = split; 171 push(@lat_tcp_local, $_[4]); 172 $tmp = $lat_tcp_local[0]; # Just to shut up the error parser 173 } else { 174 @_ = split; 175 push(@lat_tcp_net, $_[4]); 176 $tmp = $lat_tcp_net[0]; # Just to shut up the error parser 177 } 178 } 179 if (/^RPC\/udp latency using /) { 180 if(/localhost:/) { 181 @_ = split; 182 push(@lat_rpc_udp_local, $_[4]); 183 $tmp = $lat_rpc_udp_local[0]; # Just to shut up the error parser 184 } else { 185 @_ = split; 186 push(@lat_rpc_udp_net, $_[4]); 187 $tmp = $lat_rpc_udp_net[0]; # Just to shut up the error parser 188 } 189 } 190 if (/^RPC\/tcp latency using /) { 191 if(/localhost:/) { 192 @_ = split; 193 push(@lat_rpc_tcp_local, $_[4]); 194 $tmp = $lat_rpc_tcp_local[0]; # Just to shut up the error parser 195 } else { 196 @_ = split; 197 push(@lat_rpc_tcp_net, $_[4]); 198 $tmp = $lat_rpc_tcp_net[0]; # Just to shut up the error parser 199 } 200 } 201 if (/^TCP\/IP connection cost to /) { 202 if(/localhost:/) { 203 @_ = split; 204 push(@lat_tcp_connect_local, $_[5]); 205 $tmp = $lat_tcp_connect_local[0]; # Just to shut up the error parser 206 } else { 207 @_ = split; 208 push(@lat_tcp_connect_net, $_[5]); 209 $tmp = $lat_tcp_connect_net[0]; # Just to shut up the error parser 210 } 211 } 212 if (/^Socket bandwidth using /) { 213 if(/localhost:/) { 214 @_ = split; 215 push(@bw_tcp_local, $_[4]); 216 $tmp = $bw_tcp_local[0]; # Just to shut up the error parser 217 } else { 218 @_ = split; 219 push(@bw_tcp_net, $_[4]); 220 $tmp = $bw_tcp_net[0]; # Just to shut up the error parser 221 } 222 } 223 if (/^AF_UNIX sock stream bandwidth:/) { 224 @_ = split; 225 push(@bw_unix, $_[4]); 226 $tmp = $bw_unix[0]; # Just to shut up the error parser 227 } 228 if (/^Process fork.exit/) { 229 @_ = split; 230 push(@lat_nullproc, $_[2]); 231 $tmp = $lat_nullproc[0]; # Just to shut up the error parser 232 } 233 if (/^Process fork.execve:/) { 234 @_ = split; 235 push(@lat_simpleproc, $_[2]); 236 $tmp = $lat_simpleproc[0]; # Just to shut up the error parser 237 } 238 if (/^Process fork..bin.sh/) { 239 @_ = split; 240 push(@lat_shproc, $_[3]); 241 $tmp = $lat_shproc[0]; # Just to shut up the error parser 242 } 243 if (/^Pipe bandwidth/) { 244 @_ = split; 245 push(@bw_pipe, $_[2]); 246 $tmp = $bw_pipe[0]; # Just to shut up the error parser 247 } 248 if (/^File .* write bandwidth/) { 249 @_ = split; 250 $bw = sprintf("%.2f", $_[4] / 1024.); 251 push(@bw_file, $bw); 252 $tmp = $bw_file[0]; # Just to shut up the error parser 253 } 254 if (/^Pagefaults on/) { 255 @_ = split; 256 push(@lat_pagefault, $_[3]); 257 $tmp = $lat_pagefault[0]; # Just to shut up the error parser 258 } 259 if (/^"mappings/) { 260 $value = &getbiggest("memory mapping timing"); 261 push(@lat_mappings, $value); 262 $tmp = $lat_mappings[0]; # Just to shut up the error parser 263 } 264 if (/^"read bandwidth/) { 265 $value = &getbiggest("reread timing"); 266 push(@bw_reread, $value); 267 $tmp = $bw_reread[0]; # Just to shut up the error parser 268 } 269 if (/^"Mmap read bandwidth/) { 270 $value = &getbiggest("mmap reread timing"); 271 push(@bw_mmap, $value); 272 $tmp = $bw_mmap[0]; # Just to shut up the error parser 273 } 274 if (/^"libc bcopy unaligned/) { 275 $value = &getbiggest("libc bcopy timing"); 276 push(@bw_bcopy_libc, $value); 277 $tmp = $bw_bcopy_libc[0]; # Just to shut up the error parser 278 } 279 if (/^"unrolled bcopy unaligned/) { 280 $value = &getbiggest("unrolled bcopy timing"); 281 push(@bw_bcopy_unrolled, $value); 282 $tmp = $bw_bcopy_unrolled[0]; # Just to shut up the error parser 283 } 284 if (/^Memory read/) { 285 $value = &getbiggest("memory read & sum timing"); 286 push(@bw_mem_rdsum, $value); 287 $tmp = $bw_mem_rdsum[0]; # Just to shut up the error parser 288 } 289 if (/^Memory write/) { 290 $value = &getbiggest("memory write timing"); 291 push(@bw_mem_wr, $value); 292 $tmp = $bw_mem_wr[0]; # Just to shut up the error parser 293 } 294 if (/^"File system latency/) { 295 while (<FD>) { 296 next if /Id:/; 297 if (/^0k/) { 298 @_ = split; 299 push(@fs_create_0k, $_[2]); 300 push(@fs_delete_0k, $_[3]); 301 $tmp = $fs_create_0k[0]; # Just to shut up the error parser 302 $tmp = $fs_delete_0k[0]; # Just to shut up the error parser 303 } elsif (/^1k/) { 304 @_ = split; 305 push(@fs_create_1k, $_[2]); 306 push(@fs_delete_1k, $_[3]); 307 $tmp = $fs_create_1k[0]; # Just to shut up the error parser 308 $tmp = $fs_delete_1k[0]; # Just to shut up the error parser 309 } elsif (/^4k/) { 310 @_ = split; 311 push(@fs_create_4k, $_[2]); 312 push(@fs_delete_4k, $_[3]); 313 $tmp = $fs_create_4k[0]; # Just to shut up the error parser 314 $tmp = $fs_delete_4k[0]; # Just to shut up the error parser 315 } elsif (/^10k/) { 316 @_ = split; 317 push(@fs_create_10k, $_[2]); 318 push(@fs_delete_10k, $_[3]); 319 $tmp = $fs_create_10k[0]; # Just to shut up the error parser 320 $tmp = $fs_delete_10k[0]; # Just to shut up the error parser 321 } else { 322 last; 323 } 324 } 325 } 326 if (/size=0/) { 327 while (<FD>) { 328 if (/^2 /) { 329 @_ = split; push(@lat_ctx0_2, $_[1]); 330 $tmp = $lat_ctx0_2[0]; # Just to shut up the error parser 331 } elsif (/^8 /) { 332 @_ = split; push(@lat_ctx0_8, $_[1]); 333 $tmp = $lat_ctx0_8[0]; # Just to shut up the error parser 334 } elsif (/^16 /) { 335 @_ = split; push(@lat_ctx0_16, $_[1]); 336 $tmp = $lat_ctx0_16[0]; # Just to shut up the error parser 337 } 338 last if /^\s*$/ || /^Memory/; 339 } 340 } 341 if (/size=16/) { 342 while (<FD>) { 343 if (/^2 /) { 344 @_ = split; push(@lat_ctx16_2, $_[1]); 345 $tmp = $lat_ctx16_2[0]; # Just to shut up the error parser 346 } elsif (/^8 /) { 347 @_ = split; push(@lat_ctx16_8, $_[1]); 348 $tmp = $lat_ctx16_8[0]; # Just to shut up the error parser 349 } elsif (/^16 /) { 350 @_ = split; push(@lat_ctx16_16, $_[1]); 351 $tmp = $lat_ctx16_16[0]; # Just to shut up the error parser 352 } 353 last if /^\s*$/; 354 } 355 } 356 if (/size=64/) { 357 while (<FD>) { 358 if (/^2 /) { 359 @_ = split; push(@lat_ctx64_2, $_[1]); 360 $tmp = $lat_ctx64_2[0]; # Just to shut up the error parser 361 } elsif (/^8 /) { 362 @_ = split; push(@lat_ctx64_8, $_[1]); 363 $tmp = $lat_ctx64_8[0]; # Just to shut up the error parser 364 } elsif (/^16 /) { 365 @_ = split; push(@lat_ctx64_16, $_[1]); 366 $tmp = $lat_ctx64_16[0]; # Just to shut up the error parser 367 } 368 last if /^\s*$/ || /^20/; 369 } 370 } 371 if (/^"stride=128/) { 372 $save = -1; 373 while (<FD>) { 374 if (/^0.00098\s/) { 375 @_ = split; 376 push(@lat_l1, $_[1]); 377 $tmp = $lat_l1[0]; # Just to shut up the error parser 378 } elsif (/^0.12500\s/) { 379 @_ = split; 380 push(@lat_l2, $_[1]); 381 $tmp = $lat_l2[0]; # Just to shut up the error parser 382 } elsif (/^[45678].00000\s/) { 383 @_ = split; 384 $size = $_[0]; 385 $save = $_[1]; 386 last if /^8.00000\s/; 387 } elsif (/^\s*$/) { 388 last; 389 } 390 } 391 if (!/^8/) { 392 warn "$file: No 8MB memory latency, using $size\n"; 393 } 394 push(@lat_mem, $save); 395 } 396 } 397 @warn = (); 398 foreach $array ( 399 'bw_bcopy_libc', 'bw_bcopy_unrolled', 'bw_file', 400 'bw_mem_rdsum', 'bw_mem_wr', 'bw_mmap', 'bw_pipe', 401 'bw_reread', 'bw_tcp_local', 'bw_unix', 402 'fs_create_0k','fs_delete_0k', 403 'fs_create_1k','fs_delete_1k', 404 'fs_create_4k','fs_delete_4k', 405 'fs_create_10k','fs_delete_10k', 406 'lat_ctx0_16', 'lat_ctx0_2', 'lat_ctx0_8', 407 'lat_ctx16_16', 'lat_ctx16_2', 'lat_ctx16_8', 408 'lat_ctx64_16', 'lat_ctx64_2', 'lat_ctx64_8', 'lat_l1', 409 'lat_l2', 'lat_mappings', 'lat_mem', 'lat_nullproc', 410 'lat_openclose', 'lat_pagefault', 'lat_pipe', 411 'lat_protfault', 'lat_read', 412 'lat_rpc_tcp_local','lat_rpc_udp_local', 413 'lat_tcp_connect_local', 'lat_tcp_local', 'lat_udp_local', 414 'lat_rpc_tcp_net','lat_rpc_udp_net', 415 'lat_tcp_connect_net', 'lat_tcp_net', 'lat_udp_net', 416 'lat_select', 'lat_shproc', 'lat_sigcatch', 417 'lat_siginstall', 'lat_simpleproc', 'lat_stat', 418 'lat_syscall', 'lat_unix', 'lat_write', 'misc_mhz', 419 ) { 420 $last = eval '$#' . $array; 421 if ($last != $n) { 422 #warn "No data for $array in $file\n"; 423 push(@warn, $array); 424 eval 'push(@' . $array . ', -1);'; 425 } 426 } 427 if ($#warn != -1) { 428 warn "Missing data in $file: @warn\n"; 429 } 430 $n++; 431} 432 433# 434# OK, now all those arrays are packed. Because everything is keyed 435# on raw hostname, we can do all the stats evaluations using a combination 436# of @file and the array -- we march through @file and create a stats 437# object (a % hash) with its name and do the obvious sums and so forth. 438# should be very simple. 439# 440# However, to be fair to Larry, we do want to preserve the general flavor 441# of the summary. However, the summary is now going to be output BY HOST 442# and so we need a separate host-description section for each host. 443# 444# First we have to evaluate the stats, though. 445# 446 447# 448# Let's test this with just one small set of values... 449foreach $array ( 450 'bw_bcopy_libc', 'bw_bcopy_unrolled', 'bw_file', 451 'bw_mem_rdsum', 'bw_mem_wr', 'bw_mmap', 'bw_pipe', 452 'bw_reread', 'bw_tcp_local', 'bw_unix', 453 'fs_create_0k','fs_delete_0k', 454 'fs_create_1k','fs_delete_1k', 455 'fs_create_4k','fs_delete_4k', 456 'fs_create_10k','fs_delete_10k', 457 'lat_l1', 458 'lat_l2', 'lat_mappings', 'lat_mem', 'lat_nullproc', 459 'lat_openclose', 'lat_pagefault', 'lat_pipe', 460 'lat_protfault', 'lat_read', 461 'lat_rpc_tcp_local','lat_rpc_udp_local', 462 'lat_tcp_connect_local', 'lat_tcp_local', 'lat_udp_local', 463 'lat_rpc_tcp_net','lat_rpc_udp_net', 464 'lat_tcp_connect_net', 'lat_tcp_net', 'lat_udp_net', 465 'lat_select', 'lat_shproc', 'lat_sigcatch', 466 'lat_siginstall', 'lat_simpleproc', 'lat_stat', 467 'lat_syscall', 'lat_unix', 'lat_write', 'misc_mhz', 468 ) { } # Empty just to save the full list someplace handy. 469 470# 471# Oops. For some unfathomable reason lat_fs returns something other than 472# an (average) time in nanoseconds. Why, I cannot imagine -- one could 473# trivially invert so that it did so. One CANNOT DO STATS on inverse 474# quantities, so we invert here and convert to nanoseconds 475# so we can correctly do stats below. 476foreach $array ( 477 'fs_create_0k','fs_delete_0k','fs_create_1k','fs_delete_1k', 478 'fs_create_4k','fs_delete_4k','fs_create_10k','fs_delete_10k', 479 ) { 480 $cnt = 0; 481 foreach $entry (@$array){ 482 $$array[$cnt++] = 1.0e+9/$entry; 483 } 484 485} 486 487# Working copy. Let's just add things as they turn out to be 488# appropriate. In fact, we'll add them in presentation order! 489foreach $array ( 490 'lat_syscall','lat_read', 'lat_write', 'lat_syscall', 'lat_stat', 491 'lat_openclose','lat_select','lat_siginstall','lat_sigcatch', 492 'lat_nullproc','lat_simpleproc','lat_shproc', 493 'lat_ctx0_2','lat_ctx0_16','lat_ctx0_8', 494 'lat_ctx16_16','lat_ctx16_2','lat_ctx16_8', 495 'lat_ctx64_16','lat_ctx64_2','lat_ctx64_8', 496 'lat_pipe','lat_unix', 497 'lat_udp_local','lat_tcp_local',lat_tcp_connect_local, 498 'lat_rpc_udp_local','lat_rpc_tcp_local', 499 'lat_udp_net','lat_tcp_net',lat_tcp_connect_net, 500 'lat_rpc_udp_net','lat_rpc_tcp_net', 501 'fs_create_0k','fs_delete_0k', 502 'fs_create_1k','fs_delete_1k', 503 'fs_create_4k','fs_delete_4k', 504 'fs_create_10k','fs_delete_10k', 505 'lat_mappings','lat_protfault','lat_pagefault', 506 'bw_pipe','bw_unix', 507 'bw_tcp_local', # Note we need bw_udp_local as soon as it exists... 508 'bw_reread','bw_mmap','bw_bcopy_libc','bw_bcopy_unrolled', 509 'bw_mem_rdsum','bw_mem_wr', 510 'bw_tcp_net', 511 'lat_l1','lat_l2','lat_mem', 512 ) { 513 514 # 515 # This should do it all, by name and collapsed by hostname 516 # 517 makestats($array); 518 519} 520 521# 522# Fine, that seems to work. Now we break up the summary, BY HOST. 523# For each host we print just ONE TIME key values that don't really 524# vary (like its architecture information and clock). Then we print 525# out a modified version of Larry's old summary. 526# 527 528# 529# First the header 530# 531print<<EOF; 532======================================================================== 533 534 L M B E N C H 3 . 0 S U M M A R Y 535 ------------------------------------ 536 537======================================================================== 538 539EOF 540 541# 542# Now a host loop. Notice that @hosts is a list of hosts 543# 544$numhosts = @hosts; 545for($i=0;$i<$numhosts;$i++){ 546 $host = $hosts[$i]; 547 # Obviously we need a better way to fill in this information. 548 # Linux provides /proc/cpuinfo, which is just perfect and trivial 549 # to parse. However, we should probably read this in from e.g. 550 # config/$host.conf, which can be created either automagically or 551 # by hand. This file should also be used to control the running 552 # of the benchmark suite, which in turn should be done by means of 553 # a script call, not a make target. I'm getting there... 554 # 555 # Oh, one last note. It would be VERY CONVENIENT to have the config 556 # information stored in perl. So convenient that the following should 557 # BE the format of the config file... (up to the next comment) 558 $CPU = "Celeron(Mendocino)"; 559 $CPUFAMILY = "i686"; 560 $MHz = 400; 561 $L1CODE = 16; 562 $L1DATA = 16; 563 $L2SIZE = 128; 564 $memsize = 128; 565 $memspeed = "PC100"; 566 $memtype = "SDRAM"; 567 @DISKS = ("/dev/hda","/dev/hdb","/dev/hdc"); 568 @DISKTYPE = ("IBM-DJNA-371350, ATA DISK drive", "Disk 2", "Disk etc."); 569 @NETWORKS = ("ethernet-100","SneakerNet @ 3 meters/second"); 570 @NICTYPE = ("Lite-On 82c168 PNIC rev 32","Nike Sports (etc.)"); 571 @NETHUB = ("Netgear FS108 Fast Ethernet Switch","The Floor"); 572 # 573 # OK, given this wealth of detail (which can be sourced directly into 574 # the perl script from the host config file if we are clever) we now 575 # print it into the report/summary. 576 # 577 printf("HOST:\t\t$host\n"); 578 printf("CPU:\t\t$CPU\n"); 579 printf("CPU Family:\t$CPUFAMILY\n"); 580 printf("MHz:\t\t$MHz\n"); 581 printf("L1 Cache Size:\t$L1CODE KB (code)/$L1DATA KB (data)\n"); 582 printf("L2 Cache Size:\t$L2SIZE KB\n"); 583 printf("Memory:\t\t$memsize MB of $memspeed $memtype\n"); 584 printf("OS Kernel:\t%13s\n",&getos($uname[0])); 585 printf("Disk(s):\n"); 586 $numdisks = @DISKS; 587 for($j=0;$j<$numdisks;$j++){ 588 printf("\t\t%d) %s: %s\n",$j+1,$DISKS[$j],$DISKTYPE[$j]); 589 } 590 printf("Network(s):\n"); 591 $numnets = @NETWORKS; 592 for($j=0;$j<$numnets;$j++){ 593 printf("\t\t%d) %s: %s\n",$j+1,$NETWORKS[$j],$NICTYPE[$j]); 594 printf("\t\t Switch/Hub: %s\n",$NETHUB[$j]); 595 } 596 print<<EOF; 597 598 599------------------------------------------------------------------------ 600Processor, Processes - average times in microseconds - smaller is better 601------------------------------------------------------------------------ 602 null null open/ 603 call Error I/O Error stat Error close Error 604------ ------ ------ ------ ------ ------ ------ ------ 605EOF 606 607# 608# In all the output below, averaged arrays are accessed by the hash: 609# $stats{$host}{$array}{mean or stddev} (or whatever) 610 611 @fs_delete_4k = @lat_ctx0_8 = @bw_file = @lat_ctx0_16 = @fs_delete_1k = 612 @fs_create_4k = @fs_create_1k 613 if 0; # lint 614 615 # If they have no /dev/zero, use /dev/null, else average them. 616 if ($stats{$host}{lat_read}{mean} == -1) { 617 $lat_rw_mean = $stats{$host}{lat_write}{mean}; 618 $lat_rw_stddev = $stats{$host}{lat_write}{stddev}; 619 } else { 620 $lat_rw_mean = ($stats{$host}{lat_read}{mean} + $stats{$host}{lat_write}{mean})/2; 621 $lat_rw_stddev = ($stats{$host}{lat_read}{stddev} + $stats{$host}{lat_write}{stddev})/2; 622 } 623 # We have to pick a format adequate for these numbers. We'll shoot for 624 # %5.2f and see how it goes. 625 printf("%6.3f %6.3f ",$stats{$host}{lat_syscall}{mean},$stats{$host}{lat_syscall}{stddev}); 626 printf("%6.3f %6.3f ",$lat_rw_mean,$lat_rw_stddev); 627 printf("%6.3f %6.3f ",$stats{$host}{lat_stat}{mean},$stats{$host}{lat_stat}{stddev}); 628 printf("%6.3f %6.3f ",$stats{$host}{lat_openclose}{mean},$stats{$host}{lat_openclose}{stddev}); 629 # End with this to complete the line... 630 printf("\n"); 631 print<<EOF; 632........................................................................ 633 signal signal 634select Error instll Error catch Error 635------ ------ ------ ------ ------ ------ 636EOF 637 printf("%6.1f %6.2f ",$stats{$host}{lat_select}{mean},$stats{$host}{lat_select}{stddev}); 638 printf("%6.3f %6.3f ",$stats{$host}{lat_siginstall}{mean},$stats{$host}{lat_siginstall}{stddev}); 639 printf("%6.3f %6.3f ",$stats{$host}{lat_sigcatch}{mean},$stats{$host}{lat_sigcatch}{stddev}); 640 # End with this to complete the line... 641 printf("\n"); 642 print<<EOF; 643........................................................................ 644 fork exec shell 645 proc Error proc Error proc Error 646------- ------- ------- ------- ------- ------- 647EOF 648 printf("%7.1f %7.2f ", 649 $stats{$host}{lat_nullproc}{mean},$stats{$host}{lat_nullproc}{stddev}); 650 printf("%7.1f %7.2f ", 651 $stats{$host}{lat_simpleproc}{mean},$stats{$host}{lat_simpleproc}{stddev}); 652 printf("%7.1f %7.2f ", 653 $stats{$host}{lat_shproc}{mean},$stats{$host}{lat_shproc}{stddev}); 654 # End with this to complete the line... 655 printf("\n"); 656 print<<EOF; 657 658 659------------------------------------------------------------------------ 660Context switching - times in microseconds - smaller is better 661------------------------------------------------------------------------ 6622p/0K 2p/16K 2p/64K 663 Error Error Error 664------ ------ ------ ------ ------ ------ 665EOF 666 printf("%6.2f %6.3f ", 667 $stats{$host}{lat_ctx0_2}{mean},$stats{$host}{lat_ctx0_2}{stddev}); 668 printf("%6.2f %6.3f ", 669 $stats{$host}{lat_ctx16_2}{mean},$stats{$host}{lat_ctx16_2}{stddev}); 670 printf("%6.2f %6.3f ", 671 $stats{$host}{lat_ctx64_2}{mean},$stats{$host}{lat_ctx64_2}{stddev}); 672 # End with this to complete the line... 673 printf("\n"); 674 print<<EOF; 675........................................................................ 6768p/0K 8p/16K 8p/64K 677 Error Error Error 678------ ------ ------ ------ ------ ------ 679EOF 680 printf("%6.2f %6.3f ", 681 $stats{$host}{lat_ctx0_8}{mean},$stats{$host}{lat_ctx16_8}{stddev}); 682 printf("%6.2f %6.3f ", 683 $stats{$host}{lat_ctx16_8}{mean},$stats{$host}{lat_ctx16_8}{stddev}); 684 printf("%6.2f %6.3f ", 685 $stats{$host}{lat_ctx64_8}{mean},$stats{$host}{lat_ctx64_8}{stddev}); 686 # End with this to complete the line... 687 printf("\n"); 688 print<<EOF; 689........................................................................ 69016p/0K 16p/16K 16p/64K 691 Error Error Error 692------ ------ ------ ------ ------ ------ 693EOF 694 printf("%6.2f %6.3f ", 695 $stats{$host}{lat_ctx0_16}{mean},$stats{$host}{lat_ctx0_16}{stddev}); 696 printf("%6.2f %6.3f ", 697 $stats{$host}{lat_ctx16_16}{mean},$stats{$host}{lat_ctx16_16}{stddev}); 698 printf("%6.2f %6.3f ", 699 $stats{$host}{lat_ctx64_16}{mean},$stats{$host}{lat_ctx64_16}{stddev}); 700 # End with this to complete the line... 701 printf("\n"); 702 print<<EOF; 703 704------------------------------------------------------------------------ 705*Local* Communication latencies in microseconds - smaller is better 706------------------------------------------------------------------------ 707 Pipe AF 708 Error UNIX Error 709------ ------ ------ ------ 710EOF 711 printf("%6.2f %6.3f ", 712 $stats{$host}{lat_pipe}{mean},$stats{$host}{lat_pipe}{stddev}); 713 printf("%6.2f %6.3f ", 714 $stats{$host}{lat_unix}{mean},$stats{$host}{lat_unix}{stddev}); 715 printf("\n"); 716 print<<EOF; 717........................................................................ 718 UDP TCP TCP 719 Error Error Connect Error 720------ ------ ------ ------ ------ ------ 721EOF 722 printf("%6.2f %6.3f ", 723 $stats{$host}{lat_udp_local}{mean},$stats{$host}{lat_udp_local}{stddev}); 724 printf("%6.2f %6.3f ", 725 $stats{$host}{lat_tcp_local}{mean},$stats{$host}{lat_tcp_local}{stddev}); 726 printf("%6.2f %6.3f ", 727 $stats{$host}{lat_tcp_connect_local}{mean},$stats{$host}{lat_tcp_connect_local}{stddev}); 728 printf("\n"); 729 print<<EOF; 730........................................................................ 731 RPC RPC 732 UDP Error TCP Error 733------ ------ ------ ------ 734EOF 735 printf("%6.2f %6.3f ", 736 $stats{$host}{lat_rpc_udp_local}{mean},$stats{$host}{lat_rpc_udp_local}{stddev}); 737 printf("%6.2f %6.3f ", 738 $stats{$host}{lat_rpc_tcp_local}{mean},$stats{$host}{lat_rpc_tcp_local}{stddev}); 739 printf("\n"); 740 print<<EOF; 741 742------------------------------------------------------------------------ 743*Network* Communication latencies in microseconds - smaller is better 744------------------------------------------------------------------------ 745 UDP TCP TCP 746 Error Error Connect Error 747------ ------ ------ ------ ------ ------ 748EOF 749 printf("%6.2f %6.3f ", 750 $stats{$host}{lat_udp_net}{mean},$stats{$host}{lat_udp_net}{stddev}); 751 printf("%6.2f %6.3f ", 752 $stats{$host}{lat_tcp_net}{mean},$stats{$host}{lat_tcp_net}{stddev}); 753 printf("%6.2f %6.3f ", 754 $stats{$host}{lat_tcp_connect_net}{mean},$stats{$host}{lat_tcp_connect_net}{stddev}); 755 printf("\n"); 756 print<<EOF; 757........................................................................ 758 RPC RPC 759 UDP Error TCP Error 760------ ------ ------ ------ 761EOF 762 printf("%6.2f %6.3f ", 763 $stats{$host}{lat_rpc_udp_net}{mean},$stats{$host}{lat_rpc_udp_net}{stddev}); 764 printf("%6.2f %6.3f ", 765 $stats{$host}{lat_rpc_tcp_net}{mean},$stats{$host}{lat_rpc_tcp_net}{stddev}); 766 printf("\n"); 767 print<<EOF; 768 769------------------------------------------------------------------------ 770File & VM system latencies in microseconds - smaller is better 771------------------------------------------------------------------------ 772 0k File 1K File 773Create Error Delete Error Create Error Delete Error 774------- ------- ------- ------- ------- ------- ------- ------- 775EOF 776 $c0k = $stats{$host}{fs_create_0k}{mean} <= 0 ? -1 : $stats{$host}{fs_create_0k}{mean}/1000; 777 $c0kerr = $stats{$host}{fs_create_0k}{stddev} <= 0 ? -1 : $stats{$host}{fs_create_0k}{stddev}/1000; 778 $d0k = $stats{$host}{fs_delete_0k}{mean} <= 0 ? -1 : $stats{$host}{fs_delete_0k}{mean}/1000; 779 $d0kerr = $stats{$host}{fs_delete_0k}{stddev} <= 0 ? -1 : $stats{$host}{fs_delete_0k}{stddev}/1000; 780 $c1k = $stats{$host}{fs_create_1k}{mean} <= 0 ? -1 : $stats{$host}{fs_create_1k}{mean}/1000; 781 $c1kerr = $stats{$host}{fs_create_1k}{stddev} <= 0 ? -1 : $stats{$host}{fs_create_1k}{stddev}/1000; 782 $d1k = $stats{$host}{fs_delete_1k}{mean} <= 0 ? -1 : $stats{$host}{fs_delete_1k}{mean}/1000; 783 $d1kerr = $stats{$host}{fs_delete_1k}{stddev} <= 0 ? -1 : $stats{$host}{fs_delete_1k}{stddev}/1000; 784 printf("%7.2f %7.3f ", 785 $c0k,$c0kerr); 786 printf("%7.2f %7.3f ", 787 $d0k,$d0kerr); 788 printf("%7.2f %7.3f ", 789 $c1k,$c1kerr); 790 printf("%7.2f %7.3f ", 791 $d1k,$d1kerr); 792 printf("\n"); 793 print<<EOF; 794........................................................................ 795 4k File 10K File 796Create Error Delete Error Create Error Delete Error 797------- ------- ------- ------- ------- ------- ------- ------- 798EOF 799 $c4k = $stats{$host}{fs_create_4k}{mean} <= 0 ? -1 : $stats{$host}{fs_create_4k}{mean}/1000; 800 $c4kerr = $stats{$host}{fs_create_4k}{stddev} <= 0 ? -1 : $stats{$host}{fs_create_4k}{stddev}/1000; 801 $d4k = $stats{$host}{fs_delete_4k}{mean} <= 0 ? -1 : $stats{$host}{fs_delete_4k}{mean}/1000; 802 $d4kerr = $stats{$host}{fs_delete_4k}{stddev} <= 0 ? -1 : $stats{$host}{fs_delete_4k}{stddev}/1000; 803 $c10k = $stats{$host}{fs_create_10k}{mean} <= 0 ? -1 : $stats{$host}{fs_create_10k}{mean}/1000; 804 $c10kerr = $stats{$host}{fs_create_10k}{stddev} <= 0 ? -1 : $stats{$host}{fs_create_10k}{stddev}/1000; 805 $d10k = $stats{$host}{fs_delete_10k}{mean} <= 0 ? -1 : $stats{$host}{fs_delete_10k}{mean}/1000; 806 $d10kerr = $stats{$host}{fs_delete_10k}{stddev} <= 0 ? -1 : $stats{$host}{fs_delete_10k}{stddev}/1000; 807 printf("%7.2f %7.3f ", 808 $c4k,$c4kerr); 809 printf("%7.2f %7.3f ", 810 $d4k,$d4kerr); 811 printf("%7.2f %7.3f ", 812 $c10k,$c10kerr); 813 printf("%7.2f %7.3f ", 814 $d10k,$d10kerr); 815 printf("\n"); 816 print<<EOF; 817........................................................................ 818 Mmap Prot Page 819Latency Error Fault Error Fault Error 820-------- -------- ------- ------- -------- -------- 821EOF 822 printf("%8.2f %8.3f ", 823 $stats{$host}{lat_mappings}{mean},$stats{$host}{lat_mappings}{stddev}); 824 printf("%7.2f %7.3f ", 825 $stats{$host}{lat_protfault}{mean},$stats{$host}{lat_protfault}{stddev}); 826 printf("%8.2f %8.3f ", 827 $stats{$host}{lat_pagefault}{mean},$stats{$host}{lat_pagefault}{stddev}); 828 printf("\n"); 829 print<<EOF; 830 831------------------------------------------------------------------------ 832*Local* Communication bandwidths in MB/s - bigger is better 833------------------------------------------------------------------------ 834 Pipe AF 835 Error UNIX Error 836------ ------ ------ ------ 837EOF 838 printf("%6.2f %6.3f ", 839 $stats{$host}{bw_pipe}{mean},$stats{$host}{bw_pipe}{stddev}); 840 printf("%6.2f %6.3f ", 841 $stats{$host}{bw_unix}{mean},$stats{$host}{bw_unix}{stddev}); 842 printf("\n"); 843 print<<EOF; 844........................................................................ 845 UDP TCP 846 Error Error 847------ ------ ------ ------ 848EOF 849 printf("%6.2f %6.3f ", 850 -1,-1); 851 printf("%6.2f %6.3f ", 852 $stats{$host}{bw_tcp_local}{mean},$stats{$host}{bw_tcp_local}{stddev}); 853 printf("\n"); 854 print<<EOF; 855........................................................................ 856 File Mmap Bcopy Bcopy 857reread Error reread Error (libc) Error (hand) Error 858------ ------ ------ ------ ------ ------ ------ ------ 859EOF 860 printf("%6.2f %6.3f ", 861 $stats{$host}{bw_reread}{mean},$stats{$host}{bw_reread}{stddev}); 862 printf("%6.2f %6.3f ", 863 $stats{$host}{bw_mmap}{mean},$stats{$host}{bw_mmap}{stddev}); 864 printf("%6.2f %6.3f ", 865 $stats{$host}{bw_bcopy_libc}{mean},$stats{$host}{bw_bcopy_libc}{stddev}); 866 printf("%6.2f %6.3f ", 867 $stats{$host}{bw_bcopy_unrolled}{mean},$stats{$host}{bw_bcopy_unrolled}{stddev}); 868 printf("\n"); 869 print<<EOF; 870........................................................................ 871 Mem Mem 872 read Error write Error 873------ ------ ------ ------ 874EOF 875 printf("%6.2f %6.3f ", 876 $stats{$host}{bw_mem_rdsum}{mean},$stats{$host}{bw_mem_rdsum}{stddev}); 877 printf("%6.2f %6.3f ", 878 $stats{$host}{bw_mem_wr}{mean},$stats{$host}{bw_mem_wr}{stddev}); 879 printf("\n"); 880 print<<EOF; 881 882------------------------------------------------------------------------ 883*Net* Communication bandwidths in MB/s - bigger is better 884------------------------------------------------------------------------ 885 UDP TCP 886 Error Error 887------ ------ ------ ------ 888EOF 889 printf("%6.2f %6.3f ", 890 -1,-1); 891 printf("%6.2f %6.3f ", 892 $stats{$host}{bw_tcp_net}{mean},$stats{$host}{bw_tcp_net}{stddev}); 893 printf("\n"); 894 print<<EOF; 895 896------------------------------------------------------------------------ 897Memory latencies in nanoseconds - smaller is better 898 (WARNING - may not be correct, check graphs) 899------------------------------------------------------------------------ 900 L1 L2 Main 901Cache Error Cache Error mem Error Guesses 902------ ------ ------ ------ ------ ------ ------- 903EOF 904 $msg = &check_caches; 905 if ($stats{$host}{lat_l1}{mean} < 0) { 906 printf("%6s %6s ", 907 "------","------"); 908 printf("%6s %6s ", 909 "------","------"); 910 printf("%6s %6s ", 911 "------","------"); 912 printf("%6s","Bad mhz?"); 913 } else { 914 printf("%6.2f %6.3f ", 915 $stats{$host}{lat_l1}{mean},$stats{$host}{lat_l1}{stddev}); 916 printf("%6.2f %6.3f ", 917 $stats{$host}{lat_l2}{mean},$stats{$host}{lat_l2}{stddev}); 918 printf("%6.2f %6.3f ", 919 $stats{$host}{lat_mem}{mean},$stats{$host}{lat_mem}{stddev}); 920 print $msg if ($msg =~ /L/); 921 } 922 printf("\n"); 923 924 925 926# This ends the host section... 927 print<<EOF; 928 929======================================================================== 930EOF 931 932} 933 934exit 0; 935 936 937# (33, %3d) 938sub num 939{ 940 local($val, $fmt) = @_; 941 local($str) = ""; 942 local($i); 943 944 if ($val <= 0) { 945 $fmt =~ s/^.//; 946 while (length($fmt) > 1) { chop($fmt); } 947 for ($i = 0; $i < $fmt; $i++) { 948 $str .= " "; 949 } 950 return ($str); 951 } 952 $str = sprintf($fmt, $val); 953 $str; 954} 955 956# Input looks like 957# "benchmark name 958# size value 959# .... 960# <blank line> 961# 962# Return the biggest value before the blank line. 963sub getbiggest 964{ 965 local($msg) = @_; 966 local($line) = 0; 967 968 undef $save; 969 $value = 0; 970 while (<FD>) { 971 $line++; 972 #warn "$line $_"; 973 last if /^\s*$/; 974 $save = $_ if /^\d+\./; 975 } 976 if (defined $save) { 977 $_ = $save; 978 @d = split; 979 $value = $d[1]; 980 if (int($d[0]) < 4) { 981 warn "$file: using $d[0] size for $msg\n"; 982 } 983 } else { 984 warn "$file: no data for $msg\n"; 985 } 986 $value; 987} 988 989 990# Try and create sensible names from uname -a output 991sub getos 992{ 993 local(@info); 994 995 @info = split(/\s+/, $_[0]); 996 "$info[3] $info[5]"; 997} 998 999# Return true if the values differe by less than 10% 1000sub same 1001{ 1002 local($a, $b) = @_; 1003 1004 if ($a > $b) { 1005 $percent = (($a - $b) / $a) * 100; 1006 } else { 1007 $percent = (($b - $a) / $b) * 100; 1008 } 1009 return ($percent <= 20); 1010} 1011 1012sub check_caches 1013{ 1014 if (!&same($lat_l1[$i], $lat_l2[$i]) && 1015 &same($lat_l2[$i], $lat_mem[$i])) { 1016 " No L2 cache?"; 1017 } elsif (&same($lat_l1[$i], $lat_l2[$i])) { 1018 " No L1 cache?"; 1019 } 1020} 1021 1022sub makestats 1023{ 1024 1025 my $cnt=0; 1026 my $host; 1027 # Debugging 1028 # print STDERR "Ready to make stats for array $array\n"; 1029 # Zero the counters 1030 $numhosts = @hosts; 1031 for($i=0;$i<$numhosts;$i++){ 1032 $host = $hosts[$i]; 1033 $stats{$host}{$array}{mean} = 0.0; 1034 $stats{$host}{$array}{stddev} = 0.0; 1035 $stats{$host}{$array}{count} = 0; 1036 } 1037 # Loop through ALL DATA. We use the hash to direct results to 1038 # to the appropriate counters. 1039 foreach $value (@$array){ 1040 $host = $file[$cnt]; 1041 if($$array[0] == -1){ 1042 $stats{$host}{$array}{mean} = -1; 1043 $stats{$host}{$array}{stddev} = -1; 1044 # Debugging (and curiosity) 1045 print STDERR "Oops. $array is empty.\n"; 1046 return; 1047 } 1048 # Debugging 1049 # print STDERR "$host/$array ($cnt): value is $value\n"; 1050 $stats{$host}{$array}{mean} += $value; 1051 $stats{$host}{$array}{stddev} += $value*$value; 1052 $stats{$host}{$array}{count}++; 1053 $cnt++; 1054 } 1055 for($i=0;$i<$numhosts;$i++){ 1056 $host = $hosts[$i]; 1057 $cnt = $stats{$host}{$array}{count}; 1058 # Debugging Only 1059 # print STDERR "Evaluating final mean/stddev of $cnt objects in $host/$array\n"; 1060 if($cnt>1) { 1061 $stats{$host}{$array}{mean} = $stats{$host}{$array}{mean} / $cnt; 1062 $stats{$host}{$array}{stddev} = sqrt(($stats{$host}{$array}{stddev} / $cnt 1063 - $stats{$host}{$array}{mean}*$stats{$host}{$array}{mean})/($cnt-1)); 1064 } elsif($cnt == 1) { 1065 # Wish one could assign "infinity". This probably breaks somewhere. 1066 $stats{$host}{$array}{stddev} = 1.0e+1000; 1067 } else { 1068 # print STDERR "Error: Cannot average 0 $array results on $host\n"; 1069 } 1070 1071 # Debugging Only. 1072 # print STDERR "$host/$array (average): $stats{$host}{$array}{mean} +/- $stats{$host}{$array}{stddev}\n"; 1073 } 1074 1075} 1076