statsummary 37 KB

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