getsummary 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. # Generate an ascii summary from lmbench result files.
  2. # Usage: getsummary file file file...
  3. #
  4. # Hacked into existence by Larry McVoy (lm@sun.com now lm@sgi.com).
  5. # Copyright (c) 1994 Larry McVoy. GPLed software.
  6. # $Id$
  7. eval 'exec perl -Ssw $0 "$@"'
  8. if 0;
  9. # Use these constants to same typo-induced bugs later!
  10. $M = 1000000.;
  11. $K = 1000.;
  12. $n = 0;
  13. foreach $file (@ARGV) {
  14. open(FD, $file) || die "$0: can't open $file";
  15. $file =~ s/\.\d+$//;
  16. @_ = split(/\//, $file);
  17. push(@host, $_[$#_]);
  18. $file = $_[$#_ - 1];
  19. $file =~ s|/|-|;
  20. push(@file, $file);
  21. $mhz = 0;
  22. while (<FD>) {
  23. chop;
  24. next if m|scripts/lmbench: /dev/tty|;
  25. if (/^\[lmbench/) {
  26. push(@uname, $_);
  27. if (/lmbench1\./) {
  28. $version = 1;
  29. } else {
  30. $version = 2;
  31. }
  32. }
  33. if (/MHZ/ && !$mhz) {
  34. @_ = split;
  35. $_[1] =~ s/\]//;
  36. push(@misc_mhz, $_[1]);
  37. $mhz = 1;
  38. } elsif (/Mhz/ && !$mhz) {
  39. @_ = split;
  40. push(@misc_mhz, $_[0]);
  41. $mhz = 1;
  42. }
  43. if (/^Select on 100 fd/) {
  44. @_ = split;
  45. push(@lat_select, $_[4]);
  46. }
  47. if (/^Select on 100 tcp fd/) {
  48. @_ = split;
  49. push(@lat_tcp_select, $_[5]);
  50. }
  51. if (/^Simple syscall:/) {
  52. @_ = split;
  53. push(@lat_syscall, $_[2]);
  54. }
  55. if (/^Simple read:/) {
  56. @_ = split;
  57. push(@lat_read, $_[2]);
  58. }
  59. if (/^Simple write:/) {
  60. @_ = split;
  61. push(@lat_write, $_[2]);
  62. }
  63. if (/^Simple stat:/) {
  64. @_ = split;
  65. push(@lat_stat, $_[2]);
  66. }
  67. if (/^Simple open.close:/) {
  68. @_ = split;
  69. push(@lat_openclose, $_[2]);
  70. }
  71. if (/^Null syscall:/) { # Old format.
  72. @_ = split;
  73. push(@lat_write, $_[2]);
  74. }
  75. if (/^Signal handler installation:/) {
  76. @_ = split;
  77. push(@lat_siginstall, $_[3]);
  78. }
  79. if (/^Signal handler overhead:/) {
  80. @_ = split;
  81. push(@lat_sigcatch, $_[3]);
  82. }
  83. if (/^Protection fault:/) {
  84. @_ = split;
  85. push(@lat_protfault, $_[2]);
  86. }
  87. if (/^Pipe latency:/) {
  88. @_ = split;
  89. push(@lat_pipe, $_[2]);
  90. }
  91. if (/AF_UNIX sock stream latency:/) {
  92. @_ = split;
  93. push(@lat_unix, $_[4]);
  94. }
  95. if (/UDP latency using localhost:/) {
  96. @_ = split;
  97. push(@lat_udp_local, $_[4]);
  98. }
  99. if (/TCP latency using localhost/) {
  100. @_ = split;
  101. push(@lat_tcp_local, $_[4]);
  102. }
  103. if (/RPC.udp latency using localhost/) {
  104. @_ = split;
  105. push(@lat_rpc_udp_local, $_[4]);
  106. }
  107. if (/RPC.tcp latency using localhost/) {
  108. @_ = split;
  109. push(@lat_rpc_tcp_local, $_[4]);
  110. }
  111. if (/TCP.IP connection cost to localhost:/) {
  112. @_ = split;
  113. push(@lat_tcp_connect_local, $_[5]);
  114. }
  115. if (/^Socket bandwidth using localhost:/) {
  116. @_ = split;
  117. push(@bw_tcp_local, $_[4]);
  118. }
  119. if (/^AF_UNIX sock stream bandwidth:/) {
  120. @_ = split;
  121. push(@bw_unix, $_[4]);
  122. }
  123. if (/^Process fork.exit/) {
  124. @_ = split;
  125. push(@lat_nullproc, $_[2]);
  126. }
  127. if (/^Process fork.execve:/) {
  128. @_ = split;
  129. push(@lat_simpleproc, $_[2]);
  130. }
  131. if (/^Process fork..bin.sh/) {
  132. @_ = split;
  133. push(@lat_shproc, $_[3]);
  134. }
  135. if (/^Pipe bandwidth/) {
  136. @_ = split;
  137. push(@bw_pipe, $_[2]);
  138. }
  139. if (/^File .* write bandwidth/) {
  140. @_ = split;
  141. $bw = sprintf("%.2f", $_[4] / 1024.);
  142. push(@bw_file, $bw);
  143. }
  144. if (/^Pagefaults on/) {
  145. @_ = split;
  146. push(@lat_pagefault, $_[3]);
  147. }
  148. if (/^"mappings/) {
  149. $value = &getbiggest("memory mapping timing");
  150. push(@lat_mappings, $value);
  151. }
  152. if (/^"read bandwidth/) {
  153. $value = &getbiggest("reread timing");
  154. push(@bw_reread, $value);
  155. }
  156. if (/^"Mmap read bandwidth/) {
  157. $value = &getbiggest("mmap reread timing");
  158. push(@bw_mmap, $value);
  159. }
  160. if (/^"libc bcopy unaligned/) {
  161. $value = &getbiggest("libc bcopy timing");
  162. push(@bw_bcopy_libc, $value);
  163. }
  164. if (/^"unrolled bcopy unaligned/) {
  165. $value = &getbiggest("unrolled bcopy timing");
  166. push(@bw_bcopy_unrolled, $value);
  167. }
  168. if (/^Memory read/) {
  169. $value = &getbiggest("memory read & sum timing");
  170. push(@bw_mem_rdsum, $value);
  171. }
  172. if (/^Memory write/) {
  173. $value = &getbiggest("memory write timing");
  174. push(@bw_mem_wr, $value);
  175. }
  176. if (/^"File system latency/) {
  177. while (<FD>) {
  178. next if /Id:/;
  179. if (/^0k/) {
  180. @_ = split;
  181. push(@fs_create_0k, $_[2]);
  182. push(@fs_delete_0k, $_[3]);
  183. } elsif (/^1k/) {
  184. @_ = split;
  185. push(@fs_create_1k, $_[2]);
  186. push(@fs_delete_1k, $_[3]);
  187. } elsif (/^4k/) {
  188. @_ = split;
  189. push(@fs_create_4k, $_[2]);
  190. push(@fs_delete_4k, $_[3]);
  191. } elsif (/^10k/) {
  192. @_ = split;
  193. push(@fs_create_10k, $_[2]);
  194. push(@fs_delete_10k, $_[3]);
  195. } else {
  196. last;
  197. }
  198. }
  199. }
  200. if (/size=0/) {
  201. while (<FD>) {
  202. if (/^2 /) {
  203. @_ = split; push(@lat_ctx0_2, $_[1]);
  204. } elsif (/^8 /) {
  205. @_ = split; push(@lat_ctx0_8, $_[1]);
  206. } elsif (/^16 /) {
  207. @_ = split; push(@lat_ctx0_16, $_[1]);
  208. }
  209. last if /^\s*$/ || /^Memory/;
  210. }
  211. }
  212. if (/size=16/) {
  213. while (<FD>) {
  214. if (/^2 /) {
  215. @_ = split; push(@lat_ctx16_2, $_[1]);
  216. } elsif (/^8 /) {
  217. @_ = split; push(@lat_ctx16_8, $_[1]);
  218. } elsif (/^16 /) {
  219. @_ = split; push(@lat_ctx16_16, $_[1]);
  220. }
  221. last if /^\s*$/;
  222. }
  223. }
  224. if (/size=64/) {
  225. while (<FD>) {
  226. if (/^2 /) {
  227. @_ = split; push(@lat_ctx64_2, $_[1]);
  228. } elsif (/^8 /) {
  229. @_ = split; push(@lat_ctx64_8, $_[1]);
  230. } elsif (/^16 /) {
  231. @_ = split; push(@lat_ctx64_16, $_[1]);
  232. }
  233. last if /^\s*$/ || /^20/;
  234. }
  235. }
  236. if (/^"stride=128/) {
  237. $save = -1;
  238. while (<FD>) {
  239. if (/^\s*$/) {
  240. last;
  241. }
  242. @_ = split;
  243. $size = $_[0];
  244. $save = $_[1];
  245. if ($size == 0.00098) {
  246. push(@lat_l1, $_[1]);
  247. } elsif ($size == 0.12500) {
  248. push(@lat_l2, $_[1]);
  249. }
  250. }
  251. if ($size < 8.0) {
  252. warn "$file: No 8MB memory latency, using $size\n";
  253. }
  254. push(@lat_mem, $save);
  255. }
  256. }
  257. @warn = ();
  258. foreach $array (
  259. 'bw_bcopy_libc', 'bw_bcopy_unrolled', 'bw_file',
  260. 'bw_mem_rdsum', 'bw_mem_wr', 'bw_mmap', 'bw_pipe',
  261. 'bw_reread', 'bw_tcp_local', 'bw_unix', 'fs_create_0k',
  262. 'fs_create_10k', 'fs_delete_0k', 'fs_delete_10k',
  263. 'lat_ctx0_16', 'lat_ctx0_2', 'lat_ctx0_8',
  264. 'lat_ctx16_16', 'lat_ctx16_2', 'lat_ctx16_8',
  265. 'lat_ctx64_16', 'lat_ctx64_2', 'lat_ctx64_8', 'lat_l1',
  266. 'lat_l2', 'lat_mappings', 'lat_mem', 'lat_nullproc',
  267. 'lat_openclose', 'lat_pagefault', 'lat_pipe',
  268. 'lat_protfault', 'lat_read', 'lat_rpc_tcp_local',
  269. 'lat_rpc_udp_local', 'lat_select', 'lat_tcp_select',
  270. 'lat_shproc', 'lat_sigcatch',
  271. 'lat_siginstall', 'lat_simpleproc', 'lat_stat',
  272. 'lat_syscall', 'lat_tcp_connect_local', 'lat_tcp_local',
  273. 'lat_udp_local', 'lat_unix', 'lat_write', 'misc_mhz',
  274. ) {
  275. $last = eval '$#' . $array;
  276. if ($last != $n) {
  277. #warn "No data for $array in $file\n";
  278. push(@warn, $array);
  279. eval 'push(@' . $array . ', -1);';
  280. }
  281. }
  282. if ($#warn != -1) {
  283. warn "Missing data in $file: @warn\n";
  284. }
  285. $n++;
  286. }
  287. print<<EOF;
  288. L M B E N C H 2 . 0 S U M M A R Y
  289. ------------------------------------
  290. Basic system parameters
  291. ----------------------------------------------------
  292. Host OS Description Mhz
  293. --------- ------------- ----------------------- ----
  294. EOF
  295. for ($i = 0; $i <= $#uname; $i++) {
  296. printf "%-9.9s %13.13s %23.23s ", $host[$i], &getos($uname[$i]), $file[$i];
  297. printf "%4.4s\n",
  298. $misc_mhz[$i],
  299. 0;
  300. }
  301. print<<EOF;
  302. Processor, Processes - times in microseconds - smaller is better
  303. ----------------------------------------------------------------
  304. Host OS Mhz null null open selct sig sig fork exec sh
  305. call I/O stat clos TCP inst hndl proc proc proc
  306. --------- ------------- ---- ---- ---- ---- ---- ----- ---- ---- ---- ---- ----
  307. EOF
  308. @fs_delete_4k = @lat_ctx0_8 = @bw_file = @lat_ctx0_16 = @fs_delete_1k =
  309. @fs_create_4k = @fs_create_1k
  310. if 0; # lint
  311. for ($i = 0; $i <= $#uname; $i++) {
  312. # If they have no /dev/zero, use /dev/null, else average them.
  313. if ($lat_read[$i] == -1) {
  314. $tmp = $lat_write[$i];
  315. } else {
  316. $tmp = ($lat_read[$i] + $lat_write[$i]) / 2;
  317. }
  318. printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]);
  319. printf "%4.0f %4.4s %4.4s %4.4s %4.4s %5.5s %4.4s %4.4s %4.4s %4.4s %4.4s\n",
  320. $misc_mhz[$i],
  321. &num($lat_syscall[$i], 4),
  322. &num($tmp, 4),
  323. &num($lat_stat[$i], 4),
  324. &num($lat_openclose[$i], 4),
  325. &num($lat_tcp_select[$i], 5),
  326. &num($lat_siginstall[$i], 4),
  327. &num($lat_sigcatch[$i], 4),
  328. &num($lat_nullproc[$i], 4),
  329. &num($lat_simpleproc[$i], 4),
  330. &num($lat_shproc[$i], 4),
  331. 0;
  332. }
  333. print<<EOF;
  334. Context switching - times in microseconds - smaller is better
  335. -------------------------------------------------------------
  336. Host OS 2p/0K 2p/16K 2p/64K 8p/16K 8p/64K 16p/16K 16p/64K
  337. ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw
  338. --------- ------------- ----- ------ ------ ------ ------ ------- -------
  339. EOF
  340. for ($i = 0; $i <= $#uname; $i++) {
  341. printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]);
  342. printf "%5.5s %6.6s %6.6s %6.6s %6.6s %7.7s %7.7s\n",
  343. &num($lat_ctx0_2[$i], 5),
  344. &num($lat_ctx16_2[$i], 6),
  345. &num($lat_ctx64_2[$i], 6),
  346. &num($lat_ctx16_8[$i], 6),
  347. &num($lat_ctx64_8[$i], 6),
  348. &num($lat_ctx16_16[$i], 7),
  349. &num($lat_ctx64_16[$i], 7),
  350. 0;
  351. }
  352. print<<EOF;
  353. *Local* Communication latencies in microseconds - smaller is better
  354. -------------------------------------------------------------------
  355. Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP
  356. ctxsw UNIX UDP TCP conn
  357. --------- ------------- ----- ----- ---- ----- ----- ----- ----- ----
  358. EOF
  359. for ($i = 0; $i <= $#uname; $i++) {
  360. printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]);
  361. printf "%5s %5s %4s %5s %5s %5s %5s %4s\n",
  362. &num($lat_ctx0_2[$i], 5),
  363. &num($lat_pipe[$i], 5),
  364. &num($lat_unix[$i], 4),
  365. &num($lat_udp_local[$i], 5),
  366. &num($lat_rpc_udp_local[$i], 5),
  367. &num($lat_tcp_local[$i], 5),
  368. &num($lat_rpc_tcp_local[$i], 5),
  369. &num($lat_tcp_connect_local[$i], 4),
  370. 0;
  371. }
  372. print<<EOF;
  373. File & VM system latencies in microseconds - smaller is better
  374. --------------------------------------------------------------
  375. Host OS 0K File 10K File Mmap Prot Page
  376. Create Delete Create Delete Latency Fault Fault
  377. --------- ------------- ------ ------ ------ ------ ------- ----- -----
  378. EOF
  379. for ($i = 0; $i <= $#uname; $i++) {
  380. printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]);
  381. $c0k = $fs_create_0k[$i] <= 0 ? -1 : $M / $fs_create_0k[$i];
  382. $c10k = $fs_create_10k[$i] <= 0 ? -1 : $M / $fs_create_10k[$i];
  383. $d0k = $fs_delete_0k[$i] <= 0 ? -1 : $M / $fs_delete_0k[$i];
  384. $d10k = $fs_delete_10k[$i] <= 0 ? -1 : $M / $fs_delete_10k[$i];
  385. printf "%6.6s %6.6s %6.6s %6.6s %8.8s %5.5s %7.7s\n",
  386. &num($c0k, 6),
  387. &num($d0k, 6),
  388. &num($c10k, 6),
  389. &num($d10k, 6),
  390. &num($lat_mappings[$i], 8),
  391. &num($lat_protfault[$i], 5),
  392. &num($lat_pagefault[$i], 7),
  393. 0;
  394. }
  395. print<<EOF;
  396. *Local* Communication bandwidths in MB/s - bigger is better
  397. -----------------------------------------------------------
  398. Host OS Pipe AF TCP File Mmap Bcopy Bcopy Mem Mem
  399. UNIX reread reread (libc) (hand) read write
  400. --------- ------------- ---- ---- ---- ------ ------ ------ ------ ---- -----
  401. EOF
  402. for ($i = 0; $i <= $#uname; $i++) {
  403. printf "%-9.9s %13.13s ", $host[$i], &getos($uname[$i]);
  404. printf "%4.4s %4.4s %4.4s %6.6s %6.6s %6.6s %6.6s %4.4s %5.5s\n",
  405. &num($bw_pipe[$i], 4),
  406. &num($bw_unix[$i], 4),
  407. &num($bw_tcp_local[$i], 4),
  408. &num($bw_reread[$i], 6),
  409. &num($bw_mmap[$i], 6),
  410. &num($bw_bcopy_libc[$i], 6),
  411. &num($bw_bcopy_unrolled[$i], 6),
  412. &num($bw_mem_rdsum[$i], 4),
  413. &num($bw_mem_wr[$i], 5);
  414. }
  415. print<<EOF;
  416. Memory latencies in nanoseconds - smaller is better
  417. (WARNING - may not be correct, check graphs)
  418. ---------------------------------------------------
  419. Host OS Mhz L1 \$ L2 \$ Main mem Guesses
  420. --------- ------------- ---- ----- ------ -------- -------
  421. EOF
  422. for ($i = 0; $i <= $#uname; $i++) {
  423. printf "%-9.9s %13.13s %4d",
  424. $host[$i], &getos($uname[$i]), $misc_mhz[$i];
  425. $msg = &check_caches;
  426. if ($lat_l1[$i] < 0) {
  427. printf "%6s %6s %11s %s",
  428. "-", "-", "-",
  429. "Bad mhz?";
  430. } else {
  431. printf " %5.5s %6.6s %6.6s",
  432. &num($lat_l1[$i], 5),
  433. &num($lat_l2[$i], 6),
  434. &num($lat_mem[$i], 6);
  435. print $msg if ($msg =~ /L/);
  436. }
  437. print "\n";
  438. }
  439. exit 0;
  440. # (33, %3d)
  441. sub num
  442. {
  443. local($val, $len) = @_;
  444. local($str) = "";
  445. local($i);
  446. if ($val <= 0) {
  447. $str = "";
  448. for ($i = 0; $i < $len; $i++) {
  449. $str .= " ";
  450. }
  451. return ($str);
  452. }
  453. if ($val >= 10 * $M) {
  454. $nstr = sprintf("%.1f", $val / $M);
  455. $fmt = sprintf("%%%d.%ds%%s", $len - 1, $len - 1);
  456. $str = sprintf($fmt, $nstr, "M");
  457. } elsif ($val >= 10 * $K) {
  458. $nstr = sprintf("%.1f", $val / $K);
  459. $fmt = sprintf("%%%d.%ds%%s", $len - 1, $len - 1);
  460. $str = sprintf($fmt, $nstr, "K");
  461. } elsif ($val >= 10) {
  462. $nstr = sprintf("%.1f", $val);
  463. $fmt = sprintf("%%%d.%ds", $len, $len);
  464. $str = sprintf($fmt, $nstr);
  465. } else {
  466. $fmt = sprintf("%%%d.%df", $len, $len - 2);
  467. $str = sprintf($fmt, $val);
  468. }
  469. $str;
  470. }
  471. # Input looks like
  472. # "benchmark name
  473. # size value
  474. # ....
  475. # <blank line>
  476. #
  477. # Return the biggest value before the blank line.
  478. sub getbiggest
  479. {
  480. local($msg) = @_;
  481. local($line) = 0;
  482. undef $save;
  483. $value = 0;
  484. while (<FD>) {
  485. $line++;
  486. #warn "$line $_";
  487. last if /^\s*$/;
  488. $save = $_ if /^\d+\./;
  489. }
  490. if (defined $save) {
  491. $_ = $save;
  492. @d = split;
  493. $value = $d[1];
  494. if (int($d[0]) < 4) {
  495. warn "$file: using $d[0] size for $msg\n";
  496. }
  497. } else {
  498. warn "$file: no data for $msg\n";
  499. }
  500. $value;
  501. }
  502. # Try and create sensible names from uname -a output
  503. sub getos
  504. {
  505. local(@info);
  506. @info = split(/\s+/, $_[0]);
  507. "$info[3] $info[5]";
  508. }
  509. # Return true if the values differe by less than 10%
  510. sub same
  511. {
  512. local($a, $b) = @_;
  513. if ($a > $b) {
  514. $percent = (($a - $b) / $a) * 100;
  515. } else {
  516. $percent = (($b - $a) / $b) * 100;
  517. }
  518. return ($percent <= 20);
  519. }
  520. sub check_caches
  521. {
  522. if (!&same($lat_l1[$i], $lat_l2[$i]) &&
  523. &same($lat_l2[$i], $lat_mem[$i])) {
  524. " No L2 cache?";
  525. } elsif (&same($lat_l1[$i], $lat_l2[$i])) {
  526. " No L1 cache?";
  527. }
  528. }