home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume20 / plmbnchm.rks < prev    next >
Encoding:
Text File  |  1989-10-23  |  39.2 KB  |  1,314 lines

  1. Path: wuarchive!cs.utexas.edu!uunet!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v20i047:  Plum-Hall benchmarks for timing common C operations
  5. Message-ID: <2054@papaya.bbn.com>
  6. Date: 24 Oct 89 00:22:51 GMT
  7. Lines: 1304
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Eric S. Raymond <eric@snark.uu.net>
  11. Posting-number: Volume 20, Issue 47
  12. Archive-name: plum-benchmarks
  13.  
  14. This is a simple set of benchmarks intended to give programmers timing
  15. information about common C operations. See the Makefile for instructions;
  16. basically, all you have to do is type `make', wait, and look at bench.out.
  17.  
  18. A table of results for some popular machines is included in bench.tbl.
  19. For more information on the benchmark techniques and the philosophy
  20. behind them, browse the file ARTICLE.  Here's an excerpt from the article:
  21.  
  22.     We are placing into the public domain some simple  benchmarks  with
  23.     several appealing properties:
  24.     They are short enough to type while browsing at trade shows.
  25.  
  26.     They are protected against overly-aggressive compiler optimizations.
  27.  
  28.     They reflect empirically-observed operator frequencies in C programs.
  29.  
  30.     They give a C programmer information directly relevant to programming.
  31.  
  32. Enjoy!
  33. eric@snark.uu.net
  34.  
  35.  
  36. #!/bin/sh
  37. : "This is a shell archive, meaning:                              "
  38. : "1. Remove everything above the #! /bin/sh line.                "
  39. : "2. Save the resulting test in a file.                          "
  40. : "3. Execute the file with /bin/sh (not csh) to create the files:"
  41. : "    READ.ME"
  42. : "    Makefile"
  43. : "    benchdbl.c"
  44. : "    benches.c"
  45. : "    benchfn.c"
  46. : "    benchlng.c"
  47. : "    benchmul.c"
  48. : "    benchreg.c"
  49. : "    benchsho.c"
  50. : "    clock.c"
  51. : "    f3.c"
  52. : "    fround.c"
  53. : "    run-all.c"
  54. : "    benches.out"
  55. : "    run-all.out"
  56. : "    run-all.bat"
  57. : "    time-cmd.bat"
  58. : "    time-dbl.bat"
  59. : "    run-all.sh"
  60. : "    cr-lf"
  61. : "    n-n"
  62. : "    bench.tbl"
  63. : "    ARTICLE"
  64. echo file: READ.ME
  65. sed 's/^X//' >READ.ME << 'END-of-READ.ME'
  66. X            The Plum-Hall Benchmarks
  67. X
  68. XThis is a simple set of benchmarks intended to give programmers timing
  69. Xinformation about common C operations. See the Makefile for instructions;
  70. Xbasically, all you have to do is type `make', wait, and look at bench.out.
  71. X
  72. XA table of results for some popular machines is included in bench.tbl.
  73. XFor more information on the benchmark techniques and the philosophy
  74. Xbehind them, browse the file ARTICLE.
  75. X
  76. X                            Enjoy!
  77. X                        eric@snark.uu.net
  78. END-of-READ.ME
  79. echo file: Makefile
  80. sed 's/^X//' >Makefile << 'END-of-Makefile'
  81. X#
  82. X# Makefile for the Plum-Hall benchmarks package
  83. X#        by Eric S. Raymond (eric@snark.uu.net)
  84. X#
  85. X# Your system type for the benchmark list (do *not* string-quote it)
  86. XSYSTYPE = AT&T 6386/375
  87. X
  88. X# Ditto, if your headers define CLOCKS_PER_SEC
  89. XCFLAGS = -DCLOCKS_PER_SEC=60
  90. X
  91. X# Comment this out if you have ANSI clock(3)
  92. XCLOCK = clock.o
  93. X
  94. Xbench.out: nbench obench
  95. X    nbench 1 "$(SYSTYPE) (no -O)" >bench.out
  96. X    obench 1 "$(SYSTYPE) (-O)" >>bench.out
  97. X
  98. X# optimizer off
  99. Xnbench.o: benches.c
  100. X    $(CC) $(CFLAGS) -c benches.c
  101. X    mv benches.o nbench.o
  102. Xnbench: nbench.o f3.o $(CLOCK)
  103. X    cc -o nbench nbench.o f3.o $(CLOCK) -lm
  104. X
  105. X# optimizer on
  106. Xobench.o: benches.c
  107. X    $(CC) -O $(CFLAGS) -c benches.c
  108. X    mv benches.o obench.o
  109. Xobench: obench.o f3.o $(CLOCK)
  110. X    cc -o obench obench.o f3.o $(CLOCK) -lm
  111. X
  112. Xclean:
  113. X    rm -f [no]bench *.o bench.shar
  114. X
  115. Xbench.shar:
  116. X    shar READ.ME Makefile *.c *.out *.bat *.sh cr-lf n-n bench.tbl ARTICLE >bench.shar
  117. END-of-Makefile
  118. echo file: benchdbl.c
  119. sed 's/^X//' >benchdbl.c << 'END-of-benchdbl.c'
  120. X/* benchdbl - benchmark for  double   
  121. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  122. X * If machine traps overflow, use an  unsigned  type 
  123. X * Let  T  be the execution time in milliseconds
  124. X * Then  average time per operator  =  T/major  usec
  125. X * (Because the inner loop has exactly 1000 operations)
  126. X */
  127. X#define STOR_CL auto
  128. X#define TYPE double
  129. X#include <stdio.h>
  130. Xmain(ac, av)
  131. X        int ac;
  132. X        char *av[];
  133. X        {
  134. X        STOR_CL TYPE a, b, c;
  135. X        long d, major, atol();
  136. X        static TYPE m[10] = {0};
  137. X
  138. X        major = atol(av[1]);
  139. X        printf("executing %ld iterations\n", major);
  140. X        a = b = (av[1][0] - '0');
  141. X        for (d = 1; d <= major; ++d)
  142. X                {
  143. X                /* inner loop executes 1000 selected operations */
  144. X                for (c = 1; c <= 40; ++c)
  145. X                        {
  146. X                        a = a + b + c;
  147. X                        b = a * 2;
  148. X                        a = b / 10;
  149. X                        a = -a;
  150. X                        b = -a - b - c;
  151. X                        a = b == c;
  152. X                        b = a + c;
  153. X                        a = !b;
  154. X                        b = a + c;
  155. X                        a = b > c;
  156. X                        }
  157. X                }
  158. X        printf("a=%d\n", a);
  159. X        }
  160. END-of-benchdbl.c
  161. echo file: benches.c
  162. sed 's/^X//' >benches.c << 'END-of-benches.c'
  163. X/* benches - driver for Plum Hall benchmarks */
  164. X#include <stdio.h>
  165. X#include <time.h>
  166. X
  167. Xint benchreg(), benchsho(), benchlng();
  168. Xint benchmul(), benchfn(), benchdbl();
  169. X
  170. Xvoid tabulate();
  171. Xchar *fround();
  172. Xmain(argc, argv)
  173. X    int argc;
  174. X    char *argv[];
  175. X    {
  176. X    char result[6][10];
  177. X    int i;
  178. X
  179. X    if (argv[1][0] != '1')
  180. X        printf("argv[1] must be   1   !\n");
  181. X    if (argc < 3)
  182. X        {
  183. X        fprintf(stderr, "usage: benches 1 'compiler-id'\n");
  184. X        exit(2);
  185. X        }
  186. X    tabulate(benchreg, result[0]);
  187. X    tabulate(benchsho, result[1]);
  188. X    tabulate(benchlng, result[2]);
  189. X    tabulate(benchmul, result[3]);
  190. X    tabulate(benchfn,  result[4]);
  191. X    tabulate(benchdbl, result[5]);
  192. X    printf("\n\n");
  193. X    printf("%20.20s %9s %9s %9s %9s %9s %9s\n",
  194. X        "", "register", "auto", "auto", "int", "function", "auto");
  195. X    printf("%20.20s %9s %9s %9s %9s %9s %9s\n",
  196. X        "", "int", "short", "long", "multiply", "call+ret", "double");
  197. X    printf("%22.22s ",
  198. X        argv[2]);
  199. X    for (i = 0; i <= 5; ++i)
  200. X        printf("%9.9s ", result[i]);
  201. X    printf("\n");
  202. X    exit(0);
  203. X    }
  204. Xvoid tabulate(fn, s)
  205. X    void (*fn)();
  206. X    char *s;
  207. X    {
  208. X    static char arg1[20];
  209. X    static char *arga[3] = { "x", &arg1[0], 0 };
  210. X    double before, after, microsec;
  211. X    long major, major_next;
  212. X
  213. X    major_next = 1;
  214. X    do  {
  215. X        major = major_next;
  216. X        sprintf(arg1, "%ld", major);
  217. X        before = (double)clock();
  218. X        (*fn)(2, arga);
  219. X        after = (double)clock();
  220. X        major_next *= 10;
  221. X        } while (after-before < 100);
  222. X    microsec = 1e3 * (after - before) / CLOCKS_PER_SEC / major;
  223. X    sprintf(s, "%9s ", fround(microsec, 5, 3));
  224. X    }
  225. X
  226. X/* fround - round double x to precision p, n significant digits
  227. X * uses static string for result - not re-entrant
  228. X * fround is an accomodation for K+R-level printf which lacks %.*e or %g
  229. X * slow, fat version - uses sprintf
  230. X */
  231. X#include <stdio.h>
  232. Xchar *fround(x, p, n)
  233. X    double x;
  234. X    short p;
  235. X    short n;
  236. X    {
  237. X    double y;
  238. X    double log10();
  239. X    short digs;
  240. X    short nlog;
  241. X    static char s[40] = {0};
  242. X    char fmt[20];
  243. X
  244. X    sprintf(fmt, "%%.%de", n-1);
  245. X    sprintf(s, fmt, x);
  246. X    sscanf(s, "%lf", &y);
  247. X    if (y == 0)
  248. X        nlog = 0;
  249. X    else
  250. X        nlog = log10(y);
  251. X    if (nlog < 0)
  252. X        --nlog;
  253. X    digs = n - nlog - 1;
  254. X    if (digs < 0)
  255. X        digs = 0;
  256. X    else if (digs > p)
  257. X        digs = p;
  258. X    sprintf(fmt, "%%.%df", digs);
  259. X    sprintf(s, fmt, y);
  260. X    if (digs == 0)
  261. X        strcat(s, ".");
  262. X    while (digs++ < p)
  263. X        strcat(s, " ");
  264. X    return (s);
  265. X    }
  266. X
  267. X
  268. X
  269. X
  270. X#define main benchreg
  271. X#include "benchreg.c"
  272. X
  273. X#undef main
  274. X#undef STOR_CL
  275. X#undef TYPE
  276. X#define main benchsho
  277. X#include "benchsho.c"
  278. X
  279. X#undef main
  280. X#undef STOR_CL
  281. X#undef TYPE
  282. X#define main benchlng
  283. X#include "benchlng.c"
  284. X
  285. X#undef main
  286. X#undef STOR_CL
  287. X#undef TYPE
  288. X#define main benchmul
  289. X#include "benchmul.c"
  290. X
  291. X#undef main
  292. X#undef STOR_CL
  293. X#undef TYPE
  294. X#define main benchfn
  295. X#include "benchfn.c"
  296. X
  297. X#undef main
  298. X#undef STOR_CL
  299. X#undef TYPE
  300. X#define main benchdbl
  301. X#include "benchdbl.c"
  302. END-of-benches.c
  303. echo file: benchfn.c
  304. sed 's/^X//' >benchfn.c << 'END-of-benchfn.c'
  305. X/* benchfn - benchmark for function calls
  306. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  307. X * Let  T  be the execution time in milliseconds
  308. X * Then  average time per operator  =  T/major  usec
  309. X * (Because the inner loop has exactly 1000 operations)
  310. X */
  311. X#include <stdio.h>
  312. Xint dummy = 0;
  313. X
  314. Xf2() { f3();f3();f3();f3();f3();f3();f3();f3();f3();f3();} /* 10 */
  315. Xf1() { f2();f2();f2();f2();f2();f2();f2();f2();f2();f2();} /* 10 */
  316. Xf0() { f1();f1();f1();f1();f1();f1();f1();f1();f1();} /* 9 */
  317. X
  318. Xmain(ac, av)
  319. X        int ac;
  320. X        char *av[];
  321. X        {
  322. X        long d, major, atol();
  323. X
  324. X        major = atol(av[1]);
  325. X        printf("executing %ld iterations\n", major);
  326. X        for (d = 1; d <= major; ++d)
  327. X                f0(); /* executes 1000 calls */
  328. X        printf("dummy=%d\n", dummy);
  329. X        }
  330. END-of-benchfn.c
  331. echo file: benchlng.c
  332. sed 's/^X//' >benchlng.c << 'END-of-benchlng.c'
  333. X/* benchlng - benchmark for  long  integers 
  334. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  335. X * If machine traps overflow, use an  unsigned  type 
  336. X * Let  T  be the execution time in milliseconds
  337. X * Then  average time per operator  =  T/major  usec
  338. X * (Because the inner loop has exactly 1000 operations)
  339. X */
  340. X#define STOR_CL auto
  341. X#define TYPE long
  342. X#include <stdio.h>
  343. Xmain(ac, av)
  344. X        int ac;
  345. X        char *av[];
  346. X        {
  347. X        STOR_CL TYPE a, b, c;
  348. X        long d, major, atol();
  349. X        static TYPE m[10] = {0};
  350. X
  351. X        major = atol(av[1]);
  352. X        printf("executing %ld iterations\n", major);
  353. X        a = b = (av[1][0] - '0');
  354. X        for (d = 1; d <= major; ++d)
  355. X                {
  356. X                /* inner loop executes 1000 selected operations */
  357. X                for (c = 1; c <= 40; ++c)
  358. X                        {
  359. X                        a = a + b + c;
  360. X                        b = a >> 1;
  361. X                        a = b % 10;
  362. X                        m[a] = a;
  363. X                        b = m[a] - b - c;
  364. X                        a = b == c;
  365. X                        b = a | c;
  366. X                        a = !b;
  367. X                        b = a + c;
  368. X                        a = b > c;
  369. X                        }
  370. X                }
  371. X        printf("a=%d\n", a);
  372. X        }
  373. END-of-benchlng.c
  374. echo file: benchmul.c
  375. sed 's/^X//' >benchmul.c << 'END-of-benchmul.c'
  376. X/* benchmul - benchmark for  int multiply
  377. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  378. X * If machine traps overflow, use an  unsigned  type 
  379. X * Let  T  be the execution time in milliseconds
  380. X * Then  average time per operator  =  T/major  usec
  381. X * (Because the inner loop has exactly 1000 operations)
  382. X */
  383. X#define STOR_CL auto
  384. X#define TYPE int
  385. X#include <stdio.h>
  386. Xmain(ac, av)
  387. X        int ac;
  388. X        char *av[];
  389. X        {
  390. X        STOR_CL TYPE a, b, c;
  391. X        long d, major, atol();
  392. X        static TYPE m[10] = {0};
  393. X
  394. X        major = atol(av[1]);
  395. X        printf("executing %ld iterations\n", major);
  396. X        a = b = (av[1][0] - '0');
  397. X        for (d = 1; d <= major; ++d)
  398. X                {
  399. X                /* inner loop executes 1000 selected operations */
  400. X                for (c = 1; c <= 40; ++c)
  401. X                        {
  402. X                        a = 3 *a*a*a*a*a*a*a*a * a*a*a*a*a*a*a*a * a*a*a*a*a*a*a*a * a; /* 25 * */
  403. X                        }
  404. X                }
  405. X        printf("a=%d\n", a);
  406. X        }
  407. END-of-benchmul.c
  408. echo file: benchreg.c
  409. sed 's/^X//' >benchreg.c << 'END-of-benchreg.c'
  410. X/* benchreg - benchmark for  register  integers 
  411. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  412. X * If machine traps overflow, use an  unsigned  type 
  413. X * Let  T  be the execution time in milliseconds
  414. X * Then  average time per operator  =  T/major  usec
  415. X * (Because the inner loop has exactly 1000 operations)
  416. X */
  417. X#define STOR_CL register
  418. X#define TYPE int
  419. X#include <stdio.h>
  420. Xmain(ac, av)
  421. X        int ac;
  422. X        char *av[];
  423. X        {
  424. X        STOR_CL TYPE a, b, c;
  425. X        long d, major, atol();
  426. X        static TYPE m[10] = {0};
  427. X
  428. X        major = atol(av[1]);
  429. X        printf("executing %ld iterations\n", major);
  430. X        a = b = (av[1][0] - '0');
  431. X        for (d = 1; d <= major; ++d)
  432. X                {
  433. X                /* inner loop executes 1000 selected operations */
  434. X                for (c = 1; c <= 40; ++c)
  435. X                        {
  436. X                        a = a + b + c;
  437. X                        b = a >> 1;
  438. X                        a = b % 10;
  439. X                        m[a] = a;
  440. X                        b = m[a] - b - c;
  441. X                        a = b == c;
  442. X                        b = a | c;
  443. X                        a = !b;
  444. X                        b = a + c;
  445. X                        a = b > c;
  446. X                        }
  447. X                }
  448. X        printf("a=%d\n", a);
  449. X        }
  450. END-of-benchreg.c
  451. echo file: benchsho.c
  452. sed 's/^X//' >benchsho.c << 'END-of-benchsho.c'
  453. X/* benchsho - benchmark for  short  integers 
  454. X * Thomas Plum, Plum Hall Inc, 609-927-3770
  455. X * If machine traps overflow, use an  unsigned  type 
  456. X * Let  T  be the execution time in milliseconds
  457. X * Then  average time per operator  =  T/major  usec
  458. X * (Because the inner loop has exactly 1000 operations)
  459. X */
  460. X#define STOR_CL auto
  461. X#define TYPE short
  462. X#include <stdio.h>
  463. Xmain(ac, av)
  464. X        int ac;
  465. X        char *av[];
  466. X        {
  467. X        STOR_CL TYPE a, b, c;
  468. X        long d, major, atol();
  469. X        static TYPE m[10] = {0};
  470. X
  471. X        major = atol(av[1]);
  472. X        printf("executing %ld iterations\n", major);
  473. X        a = b = (av[1][0] - '0');
  474. X        for (d = 1; d <= major; ++d)
  475. X                {
  476. X                /* inner loop executes 1000 selected operations */
  477. X                for (c = 1; c <= 40; ++c)
  478. X                        {
  479. X                        a = a + b + c;
  480. X                        b = a >> 1;
  481. X                        a = b % 10;
  482. X                        m[a] = a;
  483. X                        b = m[a] - b - c;
  484. X                        a = b == c;
  485. X                        b = a | c;
  486. X                        a = !b;
  487. X                        b = a + c;
  488. X                        a = b > c;
  489. X                        }
  490. X                }
  491. X        printf("a=%d\n", a);
  492. X        }
  493. END-of-benchsho.c
  494. echo file: clock.c
  495. sed 's/^X//' >clock.c << 'END-of-clock.c'
  496. X/* clock - primitive version of ANSI 'clock' function for UNIX */
  497. Xlong clock()
  498. X    {
  499. X    struct tbuff { long pu; long ps; long cu; long cs; } tbuff;
  500. X
  501. X    times(&tbuff);
  502. X    return(tbuff.pu + tbuff.ps);
  503. X    }
  504. END-of-clock.c
  505. echo file: f3.c
  506. sed 's/^X//' >f3.c << 'END-of-f3.c'
  507. X/* f3 - lowest level function
  508. X * Put this in separate source file if compiler detects and optimizes
  509. X * useless code
  510. X */
  511. Xf3() { }
  512. END-of-f3.c
  513. echo file: fround.c
  514. sed 's/^X//' >fround.c << 'END-of-fround.c'
  515. X/* fround - round double x to precision p, n significant digits
  516. X * uses static string for result - not re-entrant
  517. X * fround is an accomodation for K+R-level printf which lacks %.*e or %g
  518. X * slow, fat version - uses sprintf
  519. X */
  520. X#include <stdio.h>
  521. Xchar *fround(x, p, n)
  522. X    double x;
  523. X    short p;
  524. X    short n;
  525. X    {
  526. X    double y;
  527. X    double log10();
  528. X    short digs;
  529. X    short nlog;
  530. X    static char s[40] = {0};
  531. X    char fmt[20];
  532. X
  533. X    sprintf(fmt, "%%.%de", n-1);
  534. X    sprintf(s, fmt, x);
  535. X    sscanf(s, "%lf", &y);
  536. X    if (y == 0)
  537. X        nlog = 0;
  538. X    else
  539. X        nlog = log10(y);
  540. X    if (nlog < 0)
  541. X        --nlog;
  542. X    digs = n - nlog - 1;
  543. X    if (digs < 0)
  544. X        digs = 0;
  545. X    else if (digs > p)
  546. X        digs = p;
  547. X    sprintf(fmt, "%%.%df", digs);
  548. X    sprintf(s, fmt, y);
  549. X    if (digs == 0)
  550. X        strcat(s, ".");
  551. X    while (digs++ < p)
  552. X        strcat(s, " ");
  553. X    return (s);
  554. X    }
  555. X#ifdef TRYMAIN
  556. Xmain()
  557. X    {
  558. X    short m;
  559. X
  560. X    for (m = 1; m <= 5; ++m)
  561. X        printf("fround(123.57, 2, %d) = %s;\n", m, fround(123.57, 2, m));
  562. X    for (m = 1; m <= 5; ++m)
  563. X        printf("fround(.013579, 5, %d) = %s;\n", m, fround(.013579, 5, m));
  564. X    }
  565. X#endif
  566. END-of-fround.c
  567. echo file: run-all.c
  568. sed 's/^X//' >run-all.c << 'END-of-run-all.c'
  569. X/* do_allbench - run all the benchmark programs */
  570. X#include <stdio.h>
  571. X#define NBENCHES 6
  572. X#define TIME_FMT "Current time is %lf:%lf:%lf"
  573. X#define CPUTIME_MIN 10000.
  574. Xstatic struct timing
  575. X    {
  576. X    double cputime; char *fname; char *title1; char *title2;
  577. X    } timings[NBENCHES] =
  578. X    {
  579. X    0., "benchreg",    "register",    "int",
  580. X    0., "benchsho",    "auto",        "short",
  581. X    0., "benchlng",    "auto",        "long",
  582. X    0., "benchmul",    "integer",    "multiply",
  583. X    0., "benchfn",    "function",    "call",
  584. X    0., "benchdbl",    "auto",        "double",
  585. X    };
  586. Xstatic char cc_cmd[BUFSIZ] = {0};
  587. Xstatic char command[BUFSIZ] = {0};
  588. Xint compile(fname)
  589. X    char *fname;
  590. X    {
  591. X    sprintf(command, cc_cmd, fname);
  592. X    return (system(command));
  593. X    }
  594. Xint mk_crlf()
  595. X    {
  596. X    FILE *crlf;
  597. X
  598. X    crlf = fopen("cr-lf", "w");
  599. X    if (crlf == NULL)
  600. X        {
  601. X        fprintf(stderr, "unable to create file  crlf\n");
  602. X        exit(2);
  603. X        }
  604. X    putc('\n', crlf);
  605. X    fclose(crlf);
  606. X    }
  607. Xdouble rd_time(tmpname)
  608. X    char *tmpname;
  609. X    {
  610. X    FILE *fp;
  611. X    double hrs, mins, secs;
  612. X
  613. X    fp = fopen(tmpname, "r");
  614. X    fgets(buf, sizeof(buf), fp);
  615. X    sscanf(buf, TIME_FMT, &hrs, &mins, &secs);
  616. X    fclose(fp);
  617. X    return (1000 * (secs + 60 * (mins + 60 * hrs));
  618. X    }
  619. Xdouble time_it(fname, iterations)
  620. X    char *fname;
  621. X    long iterations;
  622. X    {
  623. X    double t0, t1;
  624. X
  625. X    sprintf(command, "time <cr-lf >t0");
  626. X    system(command);
  627. X    t0 = rd_time("t0");
  628. X    sprintf(command, "%s %ld", fname, iterations);
  629. X    system(command);
  630. X    sprintf(command, "time <cr-lf >t1");
  631. X    system(command);
  632. X    t1 = rd_time("t1");
  633. X    return (t1 - t0);
  634. X    }
  635. Xdouble run(fname, major)
  636. X    char *fname;
  637. X    long major;
  638. X    {
  639. X    double t_empty, t_major;
  640. X
  641. X    t_empty = time_it(fname, 0L);
  642. X    t_major = time_it(fname, major);
  643. X    return (t_major - t_empty);
  644. X    }
  645. Xdouble do_all(fname)
  646. X    char *fname;
  647. X    {
  648. X    double cputime;
  649. X    long major;
  650. X
  651. X    compile(fname);
  652. X    major = MAJOR_MIN;
  653. X    do {
  654. X        cputime = run(fname, major);
  655. X        major *= 10;
  656. X        } while (cputime < CPUTIME_MIN);
  657. X    return (cputime / major);
  658. X    }
  659. Xmain(ac, av)
  660. X    int ac;
  661. X    char *av[];
  662. X    {
  663. X    int i;
  664. X
  665. X    strcpy(cc_cmd, av[1]);
  666. X    for (i = 0; i <= NBENCHES; ++i)
  667. X        timings[i].cputime = do_all(timings[i].fname);
  668. X    printf("\n\n\nRESULTS:\n\n");
  669. X    for (i = 0; i <= NBENCHES; ++i)
  670. X        printf("%10s  ", timings[i].title1;
  671. X    printf(\n");
  672. X    for (i = 0; i <= NBENCHES; ++i)
  673. X        printf("%10s  ", timings[i].title2;
  674. X    printf(\n");
  675. X    for (i = 0; i <= NBENCHES; ++i)
  676. X        printf("%10.4f  ", timings[i].cputime);
  677. X    printf("\n\n(All times are in microseconds\n");
  678. X    }
  679. END-of-run-all.c
  680. echo file: benches.out
  681. sed 's/^X//' >benches.out << 'END-of-benches.out'
  682. Xexecuting 1 iterations
  683. Xa=0
  684. Xexecuting 10 iterations
  685. Xa=0
  686. Xexecuting 100 iterations
  687. Xa=0
  688. Xexecuting 1000 iterations
  689. Xa=0
  690. Xexecuting 10000 iterations
  691. Xa=0
  692. Xexecuting 1 iterations
  693. Xa=0
  694. Xexecuting 10 iterations
  695. Xa=0
  696. Xexecuting 100 iterations
  697. Xa=0
  698. Xexecuting 1000 iterations
  699. Xa=0
  700. Xexecuting 10000 iterations
  701. Xa=0
  702. Xexecuting 1 iterations
  703. Xa=0
  704. Xexecuting 10 iterations
  705. Xa=0
  706. Xexecuting 100 iterations
  707. Xa=0
  708. Xexecuting 1000 iterations
  709. Xa=0
  710. Xexecuting 10000 iterations
  711. Xa=0
  712. Xexecuting 1 iterations
  713. Xa=-407629151
  714. Xexecuting 10 iterations
  715. Xa=-483154367
  716. Xexecuting 100 iterations
  717. Xa=-1034506623
  718. Xexecuting 1000 iterations
  719. Xa=-1045589759
  720. Xexecuting 1 iterations
  721. Xdummy=0
  722. Xexecuting 10 iterations
  723. Xdummy=0
  724. Xexecuting 100 iterations
  725. Xdummy=0
  726. Xexecuting 1000 iterations
  727. Xdummy=0
  728. Xexecuting 1 iterations
  729. Xa=0
  730. Xexecuting 10 iterations
  731. Xa=0
  732. Xexecuting 100 iterations
  733. Xa=0
  734. X
  735. X
  736. X                      register      auto      auto       int  function      auto
  737. X                           int     short      long  multiply  call+ret    double
  738. X             xenix-386   0.24      0.46      0.43      1.87      3.00     90.5     
  739. END-of-benches.out
  740. echo file: run-all.out
  741. sed 's/^X//' >run-all.out << 'END-of-run-all.out'
  742. X+ cc -o benchfn.x benchfn.c 
  743. Xbenchfn.c
  744. X+ time benchfn.x 1000 
  745. Xexecuting 1000 iterations
  746. Xdummy=0
  747. X
  748. Xreal         3.3
  749. Xuser         3.1
  750. Xsys          0.0
  751. X+ cc -o benchmul.x benchmul.c 
  752. Xbenchmul.c
  753. X+ time benchmul.x 10000 
  754. Xexecuting 10000 iterations
  755. Xa=427469313
  756. X
  757. Xreal        19.0
  758. Xuser        18.8
  759. Xsys          0.1
  760. X+ cc -o benchlng.x benchlng.c 
  761. Xbenchlng.c
  762. X+ time benchlng.x 10000 
  763. Xexecuting 10000 iterations
  764. Xa=0
  765. X
  766. Xreal         5.1
  767. Xuser         5.0
  768. Xsys          0.0
  769. X+ cc -o benchsho.x benchsho.c 
  770. Xbenchsho.c
  771. X+ time benchsho.x 10000 
  772. Xexecuting 10000 iterations
  773. Xa=0
  774. X
  775. Xreal         5.2
  776. Xuser         5.1
  777. Xsys          0.1
  778. X+ cc -o benchreg.x benchreg.c 
  779. Xbenchreg.c
  780. X+ time benchreg.x 10000 
  781. Xexecuting 10000 iterations
  782. Xa=0
  783. X
  784. Xreal         2.6
  785. Xuser         2.5
  786. Xsys          0.0
  787. X+ cc -o benchdbl.x benchdbl.c 
  788. Xbenchdbl.c
  789. X+ time benchdbl.x 10000 
  790. Xexecuting 10000 iterations
  791. Xa=0
  792. X
  793. Xreal     15:04.5
  794. Xuser     15:04.4
  795. Xsys          0.1
  796. END-of-run-all.out
  797. echo file: run-all.bat
  798. sed 's/^X//' >run-all.bat << 'END-of-run-all.bat'
  799. Xcl benchreg.c
  800. Xcommand /c time-cmd benchreg >benchreg.out
  801. X
  802. Xcl benchsho.c
  803. Xcommand /c time-cmd benchsho >benchsho.out
  804. X
  805. Xcl benchlng.c
  806. Xcommand /c time-cmd benchlng >benchlng.out
  807. X
  808. Xcl benchfn.c
  809. Xcommand /c time-cmd benchfn >benchfn.out
  810. X
  811. Xcl benchmul.c
  812. Xcommand /c time-cmd benchmul >benchmul.out
  813. X
  814. Xcl benchdbl.c
  815. Xcommand /c time-cmd benchdbl >benchdbl.out
  816. X
  817. END-of-run-all.bat
  818. echo file: time-cmd.bat
  819. sed 's/^X//' >time-cmd.bat << 'END-of-time-cmd.bat'
  820. Xtime <cr-lf
  821. X%1 0
  822. Xtime <cr-lf
  823. X%1 10000
  824. Xtime <cr-lf
  825. END-of-time-cmd.bat
  826. echo file: time-dbl.bat
  827. sed 's/^X//' >time-dbl.bat << 'END-of-time-dbl.bat'
  828. Xtime <cr-lf
  829. Xbenchdbl 0
  830. Xtime <cr-lf
  831. Xbenchdbl 100
  832. Xtime <cr-lf
  833. END-of-time-dbl.bat
  834. echo file: run-all.sh
  835. sed 's/^X//' >run-all.sh << 'END-of-run-all.sh'
  836. Xcc -o benchfn.x benchfn.c
  837. Xtime benchfn.x  1000
  838. Xcc -o benchmul.x benchmul.c
  839. Xtime benchmul.x  10000
  840. Xcc -o benchlng.x benchlng.c
  841. Xtime benchlng.x  10000
  842. Xcc -o benchsho.x benchsho.c
  843. Xtime benchsho.x  10000
  844. Xcc -o benchreg.x benchreg.c
  845. Xtime benchreg.x  10000
  846. Xcc -o benchdbl.x benchdbl.c
  847. Xtime benchdbl.x  10000
  848. END-of-run-all.sh
  849. echo file: cr-lf
  850. sed 's/^X//' >cr-lf << 'END-of-cr-lf'
  851. X
  852. END-of-cr-lf
  853. echo file: n-n
  854. sed 's/^X//' >n-n << 'END-of-n-n'
  855. Xn
  856. Xn
  857. END-of-n-n
  858. echo file: bench.tbl
  859. sed 's/^X//' >bench.tbl << 'END-of-bench.tbl'
  860. XMachine/compiler    register   auto       auto     int        func    auto
  861. X                    int        short      long     multiply   call    dbl
  862. X
  863. XAT&T 3B2/05 (-O)      1.36      3.87      2.62     15.4       7.7     22.5
  864. XAT&T 3B2/05 (no -O)   1.78      4.66      2.75     16.2       9.3     22.5
  865. XAT&T 3B2/400 (-O)     1.09      1.36      1.10     16.2      10.0(?)  91.4
  866. XAT&T 3B2/400 (no -O)  1.14      2.61      2.36     17.3      11.3     91.1
  867. XAT&T 6386/375 (no -O) 0.61      1.39      1.23      3.85      5.62     6.77    
  868. XAT&T 6386/375 (-O)    0.52      1.17      0.54      3.68      5.78     7.68    
  869. XApollo DN330 (-O)     1.36       .78      1.36     10.17      3.57
  870. XApollo DN330 (no -O)  1.54      1.28      1.54     11.30      3.64
  871. XApollo DN580 (-O)     1.03       .59      1.03      7.67      2.72
  872. XApollo DN580 (no -O)  1.18       .97      1.18      8.48      2.77
  873. XApollo DN660 (_O)     5.88      1.24      5.88     21.86      4.26
  874. XApollo DN660 (no -O)  5.93      1.52      5.93     21.93      4.29
  875. XMasscomp 5500         3.18      2.7       4.9      30.8       7.3
  876. XMasscomp 5600 (-O)     .45       .61       .46      2.83      1.04
  877. XMasscomp 5600 (no -O)  .46       .78       .64      2.99      1.76
  878. XPC/8088 (InstantC)   25.8      25.8      82.0      74.2     152.
  879. XPC/8088 (WSL 3.1 lg)  6.18     10.4      66.5      31.8      28.8
  880. XPyramid 90X (-O)       .85      1.04       .86      3.64      1.9      2.37
  881. XPyramid 90X (no -O)    .86      1.01       .86      3.65      1.8      2.34
  882. XSequent (-O)          1.39      2.99      2.53      9.90      9.3
  883. XSequent (no -O)       1.50      3.25      2.83      9.95     13.2
  884. XSun 3/260HM (-O)       .31       .48       .47      1.98      1.16
  885. XSun 3/260HM (no -O)    .36       .58       .57      1.99      1.62
  886. XSun 3/75M (-O)         .47       .77       .76      3.00      2.12
  887. XSun 3/75M (no -O)      .53       .95       .94      3.01      2.73
  888. XSun 3/75M(4.2, -O)     .50       .81       .83      2.85      1.5     20.7
  889. XSun 3/75M(4.2, no -O)  .54      1.00      1.01      2.97      2.7     21.1
  890. XSun 3/75M(VM, -O)      .46       .77       .75      2.96      2.1     20.8
  891. XSun 3/75M(VM, no -O)   .52       .96       .93      2.97      2.7     21.1
  892. XVAX 11/730 (-O)       4.00      9.80      6.20     16.2      42.8     12.4
  893. XVAX 11/730 (no -O)    4.73     10.2       7.45     16.57     51.5     17.0
  894. XVAX 11/780 (-O)       1.21      2.43      1.67      2.76     15.04     2.95
  895. XVAX 11/780 (BSD 4.2)  1.38      2.42      1.96      2.92     17.2
  896. XVAX 11/780 (UNIX 5.2) 1.24      2.48      1.79      2.72     15.7      3.89
  897. XVAX 11/780 (no -O)    1.29      2.51      1.85      2.70     16.7      3.89
  898. XVAX 11/785 (-O)        .93      1.85      1.32      5.00     13.9     47.5
  899. XVAX 11/785 (no -O)    1.01      1.96      1.44      5.08     14.2      5.42
  900. XVAX 8650(UNIX -O)      .236      .484      .298      .589     2.63      .578
  901. XVAX 8650(UNIX no -O)   .258      .482      .316      .574     3.06      .791
  902. XVAX 8650(Ultrix -O)    .23       .40       .29       .53      2.4       .56
  903. XVAX 8650(Ultrix no -O) .26       .41       .34       .56      2.8       .77
  904. END-of-bench.tbl
  905. echo file: ARTICLE
  906. sed 's/^X//' >ARTICLE << 'END-of-ARTICLE'
  907. X
  908. X
  909. X
  910. X
  911. X
  912. X
  913. X[The following article appeared in  "C Users Journal" May 1988.
  914. X It describes the purpose and use of the enclosed benchmarks. ]
  915. X
  916. X
  917. XSIMPLE BENCHMARKS FOR C COMPILERS
  918. X
  919. Xby Thomas Plum
  920. X
  921. XDr.Plum is the author of several books on  C,  including  Efficient  C  (co-
  922. Xauthored  with  Jim  Brodie).  He is Vice-Chair of the ANSI X3J11 Committee,
  923. Xand Chairman of Plum Hall Inc, which offers introductory and  advanced  sem-
  924. Xinars on C.
  925. X
  926. XCopyright (c) 1988, Plum Hall Inc
  927. X
  928. X
  929. XWe are placing into the public domain some simple  benchmarks  with  several
  930. Xappealing properties:
  931. X
  932. X    They are short enough to type while browsing at trade shows.
  933. X
  934. X    They are protected against overly-aggressive compiler optimizations.
  935. X
  936. X    They reflect empirically-observed operator frequencies in C programs.
  937. X
  938. X    They give a C programmer information directly relevant to programming.
  939. X
  940. XIn Efficient C, Jim Brodie and I described how useful it can be for  a  pro-
  941. Xgrammer  to have a general idea of how many microseconds it takes to execute
  942. Xthe "average operator" on   register  int's,  on   auto  short's,  on   auto
  943. Xlong's,  and  on  double  data, as well as the time for an integer multiply,
  944. Xand the time to call-and-return from a function.  These six numbers allow  a
  945. Xprogrammer  to  make  very good first-order estimates of the CPU time that a
  946. Xparticular algorithm will take.
  947. X
  948. XThe  following  easily-typed  benchmark  programs  determine   these   times
  949. Xdirectly.   The  first  one  is  benchreg.c  ("benchmark for register opera-
  950. Xtors"):
  951. X
  952. X
  953. X
  954. X
  955. X
  956. X
  957. X
  958. X
  959. X
  960. X
  961. X
  962. X
  963. X
  964. X
  965. X
  966. X
  967. X
  968. X
  969. X
  970. X
  971. X
  972. X                                   - 1 -
  973. X
  974. X
  975. X
  976. X
  977. X
  978. X                                   - 2 -
  979. X
  980. X
  981. X    1   /* benchreg - benchmark for  register  integers
  982. X    2    * Thomas Plum, Plum Hall Inc, 609-927-3770
  983. X    3    * If machine traps overflow, use an  unsigned  type
  984. X    4    * Let  T  be the execution time in milliseconds
  985. X    5    * Then  average time per operator  =  T/major  usec
  986. X    6    * (Because the inner loop has exactly 1000 operations)
  987. X    7    */
  988. X    8   #define STOR_CL register
  989. X    9   #define TYPE int
  990. X   10   #include <stdio.h>
  991. X   11   main(ac, av)
  992. X   12           int ac;
  993. X   13           char *av[];
  994. X   14           {
  995. X   15           STOR_CL TYPE a, b, c;
  996. X   16           long d, major, atol();
  997. X   17           static TYPE m[10] = {0};
  998. X   18
  999. X   19           major = atol(av[1]);
  1000. X   20           printf("executing %ld iterations0, major);
  1001. X   21           a = b = (av[1][0] - '0');
  1002. X   22           for (d = 1; d <= major; ++d)
  1003. X   23                   {
  1004. X   24                   /* inner loop executes 1000 selected operations */
  1005. X   25                   for (c = 1; c <= 40; ++c)
  1006. X   26                           {
  1007. X   27                           a = a + b + c;
  1008. X   28                           b = a >> 1;
  1009. X   29                           a = b % 10;
  1010. X   30                           m[a] = a;
  1011. X   31                           b = m[a] - b - c;
  1012. X   32                           a = b == c;
  1013. X   33                           b = a | c;
  1014. X   34                           a = !b;
  1015. X   35                           b = a + c;
  1016. X   36                           a = b > c;
  1017. X   37                           }
  1018. X   38                   }
  1019. X   39           printf("a=%d0, a);
  1020. X   40           }
  1021. X
  1022. XIf you enter this and compile it to produce an executable program,  you  can
  1023. Xinvoke it with one argument, the number of iterations for the major loop:
  1024. X
  1025. X    benchreg  10000
  1026. X
  1027. XIf this execution takes 16 seconds, this means that  the  average   register
  1028. Xoperation  takes  1.6  microseconds  (16,000  milliseconds divided by 10,000
  1029. Xiterations of the major loop).
  1030. X
  1031. XLet us examine the program  in  detail.   Lines  8  and  9  define   STOR_CL
  1032. X("storage  class")  and  TYPE  to be register  and  int .  Thus, on line 15,
  1033. Xthree variables ( a , b , and  c ) are declared to be of this storage  class
  1034. Xand type.  At line 16, the major loop control variables are  long  integers,
  1035. Xbut they are touched only one one-thousandth as  often  as  the  inner  loop
  1036. X
  1037. X
  1038. X
  1039. X
  1040. X
  1041. X
  1042. X
  1043. X
  1044. X                                   - 3 -
  1045. X
  1046. X
  1047. Xvariables, so they have little effect upon the timings.   We  are  declaring
  1048. Xthe   atol   function to return a  long  integer; it would otherwise default
  1049. Xto an  int  return.  (If we were using a compiler based upon draft  ANSI  C,
  1050. Xwe  could   #include  <stdlib.h>  to get the declaration of  atol , but this
  1051. Xwould limit the applicability of the benchmarks.  This simple declaration is
  1052. Xall that even an ANSI compiler would need.)
  1053. X
  1054. XAt line 19, we set the  major  loop variable to the number given on the com-
  1055. Xmand line, and at line 20, we confirm it to the output.
  1056. X
  1057. XLine 21 is crucial to preventing some overly aggressive optimizations.  Ear-
  1058. Xlier  versions  of  these benchmarks had simply initialized  a  and  b to 1,
  1059. Xbut this allows a compiler to forward-propagate a known constant value.  The
  1060. Xexpression   av[1][0]   gives  the first digit-character of the command-line
  1061. Xargument; subtracting  '0'  produces a digit between 0  and  9.   (Yes,  the
  1062. Xlatest  ANSI draft now guarantees that the digit characters are a contiguous
  1063. Xsequence in any environment.)
  1064. X
  1065. XLine 22 simply executes the major loop the number  of  times  given  by  the
  1066. Xvariable   major  .   Line  25  repeats the inner loop 40 times, and with 25
  1067. Xoperators in that loop, this produces 1000 operators.  (Actually  there  are
  1068. X1003, because of the initialization and the extra increment and test at loop
  1069. Xcompletion.  The discrepancy is well within acceptable tolerances.)
  1070. X
  1071. XWithin the inner loop, 40% of the operators are assignments, in keeping with
  1072. Xthe  percentages  reported  in  the  original  Drhystone work.  Of the other
  1073. Xoperators, the most frequent are plus and minus.  The sequence of operations
  1074. Xis  carefully  chosen to ensure that a very aggressive optimizer cannot find
  1075. Xany useless code sections; each result depends  functionally  upon  previous
  1076. Xresults.
  1077. X
  1078. XFinally, the printout at line 39  is  also  important  to  preventing  over-
  1079. Xoptimization.   If  the  compiler  could notice that we did nothing with the
  1080. Xcomputed result, it could discard all  the  operations  that  produced  that
  1081. Xresult.
  1082. X
  1083. XWe have completed our perusal of the first benchmark program,  benchreg.c  .
  1084. XThe second program (  benchsho.c , for  short's) is derived from  benchreg.c
  1085. Xby changing lines 8 and 9:  STOR_CL  becomes   auto  ,  and   TYPE   becomes
  1086. Xshort .  The program is otherwise unchanged.
  1087. X
  1088. XThe third program (  benchlng.c  ,  for   long's)  is  obtained  by  leaving
  1089. XSTOR_CL  as  auto and changing  TYPE  to  long .
  1090. X
  1091. XTo make the fourth program ( benchmul.c , for multiplies) we set   TYPE   to
  1092. Xint , and change lines 27 through 36 to one source line which does 25 multi-
  1093. Xplies:
  1094. X
  1095. X    a = 3 *a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a; /* 25 * */
  1096. X
  1097. XThe fifth program ( benchfn.c , for  functions)  is  a  major  rewrite.   We
  1098. Xarrange  a series of function definitions for  f3 ,  f2 ,  f1 , and  f0 such
  1099. Xthat each call to function  f0  generates exactly 1000 function-call  opera-
  1100. Xtions.   In case the compiler has an aggressive optimizer, move the function
  1101. Xf3  to a separate source file, so that the compiler cannot see  how  useless
  1102. X
  1103. X
  1104. X
  1105. X
  1106. X
  1107. X
  1108. X
  1109. X
  1110. X                                   - 4 -
  1111. X
  1112. X
  1113. Xit is.  The global variable  dummy  will make the compiler  think  that   f3
  1114. Xmight be up to something useful.  Here, then, is the  benchfn.c  function:
  1115. X
  1116. X    1   /* benchfn - benchmark for function calls
  1117. X    2    * Thomas Plum, Plum Hall Inc, 609-927-3770
  1118. X    3    * Let  T  be the execution time in milliseconds
  1119. X    4    * Then  average time per operator  =  T/major  usec
  1120. X    5    * (Because the inner loop has exactly 1000 operations)
  1121. X    6    */
  1122. X    7   #include <stdio.h>
  1123. X    8   int dummy = 0;
  1124. X    9
  1125. X   10   /* f3 - lowest level function
  1126. X   11    * Put this in separate source file if compiler detects and
  1127. X   12    * optimizes useless code
  1128. X   13    */
  1129. X   14   f3() { }
  1130. X   15
  1131. X   16   f2() { f3();f3();f3();f3();f3();f3();f3();f3();f3();f3();} /* 10 */
  1132. X   17   f1() { f2();f2();f2();f2();f2();f2();f2();f2();f2();f2();} /* 10 */
  1133. X   18   f0() { f1();f1();f1();f1();f1();f1();f1();f1();f1();} /* 9 */
  1134. X   19
  1135. X   20   main(ac, av)
  1136. X   21           int ac;
  1137. X   22           char *av[];
  1138. X   23           {
  1139. X   24           long d, major, atol();
  1140. X   25
  1141. X   26           major = atol(av[1]);
  1142. X   27           printf("executing %ld iterations0, major);
  1143. X   28           for (d = 1; d <= major; ++d)
  1144. X   29                   f0(); /* executes 1000 calls */
  1145. X   30           printf("dummy=%d0, dummy);
  1146. X   31           }
  1147. X
  1148. XThe sixth program ( benchdblc. , for  double's ) is derived from  benchlng.c
  1149. Xby  changing  STOR_CL  to  auto , TYPE  to  double , and replacing the inner
  1150. Xloop body with this slightly different version:
  1151. X
  1152. X    a = a + b + c;
  1153. X    b = a * 2;
  1154. X    a = b / 10;
  1155. X    a = -a;
  1156. X    b = -a - b - c;
  1157. X    a = b == c;
  1158. X    b = a + c;
  1159. X    a = !b;
  1160. X    b = a + c;
  1161. X    a = b > c;
  1162. X
  1163. XThese changes are necessary because floating-point operands are not  allowed
  1164. Xfor  the  shift, remainder, and bitwise operators, and because the subscript
  1165. Xoperator does not really exercise  the  floating-point  instructions.   This
  1166. Xrevised  inner  loop  still  gives us a representative mix of typical opera-
  1167. Xtions.
  1168. X
  1169. X
  1170. X
  1171. X
  1172. X
  1173. X
  1174. X
  1175. X
  1176. X                                   - 5 -
  1177. X
  1178. X
  1179. XThis, then, completes our collection of six benchmark programs.  After  they
  1180. Xare  compiled to produce executable programs, the next question is "How do I
  1181. Xtime the execution?"
  1182. X
  1183. XOn UNIX systems, the timing is easy -- just run the  time  command:
  1184. X
  1185. X    $ time benchreg 10000
  1186. X
  1187. XThe sum of the "user" and "system" times will give the CPU time used by  the
  1188. Xprogram.
  1189. X
  1190. XMore accurately, we could time the execution of zero  iterations,  and  sub-
  1191. Xtract that time from the time for the measured number of iterations.
  1192. X
  1193. XOn MS-DOS systems, timings can be obtained, but with greater difficulty.  If
  1194. Xwe  create  a  file  named   CR-LF   which  contains  just  one  newline (or
  1195. X"carriage-return-newline" in DOS parlance), we could time our program with a
  1196. X"batch" file such as this:
  1197. X
  1198. X    time <cr-lf
  1199. X    benchreg 0
  1200. X    time <cr-lf
  1201. X    benchreg 10000
  1202. X    time <cr-lf
  1203. X
  1204. XWe must then take times that are expressed in minutes-and-seconds  and  pro-
  1205. Xduce differences expressed in seconds.
  1206. X
  1207. XWith whichever method, we eventually produce six numbers that are character-
  1208. Xistic of a particular environment (a specific compiler supporting a specific
  1209. Xmachine).
  1210. X
  1211. X[NOTE: Since this article appeared, I have added a driver program,  benches.c.
  1212. XIn an ANSI environment with the  clock  function, it will run all the tests
  1213. Xand report the results, eliminating the need for manual computations.]
  1214. X
  1215. XHere are some examples of timing  results  that  have  been  obtained  on  a
  1216. Xvariety of minicomputer and workstation environments:
  1217. X
  1218. X
  1219. X
  1220. X
  1221. X
  1222. X
  1223. X
  1224. X
  1225. X
  1226. X
  1227. X
  1228. X
  1229. X
  1230. X
  1231. X
  1232. X
  1233. X
  1234. X
  1235. X
  1236. X
  1237. X
  1238. X
  1239. X
  1240. X
  1241. X
  1242. X                                   - 6 -
  1243. X
  1244. X
  1245. XMachine/compiler    register   auto       auto     int        func    auto
  1246. X                    int        short      long     multiply   call    dbl
  1247. X
  1248. XAT&T 3B2/05 (-O)      1.36      3.87      2.62     15.4       7.7     22.5
  1249. XAT&T 3B2/05 (no -O)   1.78      4.66      2.75     16.2       9.3     22.5
  1250. XAT&T 3B2/400 (-O)     1.09      1.36      1.10     16.2      10.0(?)  91.4
  1251. XAT&T 3B2/400 (no -O)  1.14      2.61      2.36     17.3      11.3     91.1
  1252. XApollo DN330 (-O)     1.36       .78      1.36     10.17      3.57
  1253. XApollo DN330 (no -O)  1.54      1.28      1.54     11.30      3.64
  1254. XApollo DN580 (-O)     1.03       .59      1.03      7.67      2.72
  1255. XApollo DN580 (no -O)  1.18       .97      1.18      8.48      2.77
  1256. XApollo DN660 (-O)     5.88      1.24      5.88     21.86      4.26
  1257. XApollo DN660 (no -O)  5.93      1.52      5.93     21.93      4.29
  1258. XCray X-MP (no vectors) .0567     .0656     .0822     .366      .821     .082
  1259. XMasscomp 5500         3.18      2.7       4.9      30.8       7.3
  1260. XMasscomp 5600 (-O)     .45       .61       .46      2.83      1.04
  1261. XMasscomp 5600 (no -O)  .46       .78       .64      2.99      1.76
  1262. XPyramid 90X (-O)       .85      1.04       .86      3.64      1.9      2.37
  1263. XPyramid 90X (no -O)    .86      1.01       .86      3.65      1.8      2.34
  1264. XSequent (-O)          1.39      2.99      2.53      9.90      9.3
  1265. XSequent (no -O)       1.50      3.25      2.83      9.95     13.2
  1266. XSun 3/260HM (-O)       .31       .48       .47      1.98      1.16
  1267. XSun 3/260HM (no -O)    .36       .58       .57      1.99      1.62
  1268. XSun 3/75M (-O)         .47       .77       .76      3.00      2.12
  1269. XSun 3/75M (no -O)      .53       .95       .94      3.01      2.73
  1270. XSun 3/75M(4.2, -O)     .50       .81       .83      2.85      1.5     20.7
  1271. XSun 3/75M(4.2, no -O)  .54      1.00      1.01      2.97      2.7     21.1
  1272. XSun 3/75M(VM, -O)      .46       .77       .75      2.96      2.1     20.8
  1273. XSun 3/75M(VM, no -O)   .52       .96       .93      2.97      2.7     21.1
  1274. XVAX 11/730 (-O)       4.00      9.80      6.20     16.2      42.8     12.4
  1275. XVAX 11/730 (no -O)    4.73     10.2       7.45     16.57     51.5     17.0
  1276. XVAX 11/780 (-O)       1.21      2.43      1.67      2.76     15.0      2.95
  1277. XVAX 11/780 (BSD 4.2)  1.38      2.42      1.96      2.92     17.2
  1278. XVAX 11/780 (UNIX 5.2) 1.24      2.48      1.79      2.72     15.7      3.89
  1279. XVAX 11/780 (no -O)    1.29      2.51      1.85      2.70     16.7      3.89
  1280. XVAX 11/785 (-O)        .93      1.85      1.32      5.00     13.9     47.5
  1281. XVAX 11/785 (no -O)    1.01      1.96      1.44      5.08     14.2      5.42
  1282. XVAX 8650(UNIX -O)      .236      .484      .298      .589     2.63      .578
  1283. XVAX 8650(UNIX no -O)   .258      .482      .316      .574     3.06      .791
  1284. XVAX 8650(Ultrix -O)    .23       .40       .29       .53      2.4       .56
  1285. XVAX 8650(Ultrix no -O) .26       .41       .34       .56      2.8       .77
  1286. X
  1287. XNotice that some of these timings were run before the   benchdbl   benchmark
  1288. Xhad  been  written.  There are no examples of the popular PC environments in
  1289. Xthis table.  If interested readers wish to run these benchmarks on their own
  1290. Xenvironments, I will endeavor to present these results in a future article.
  1291. X
  1292. XProcessor speeds are sometimes described in "MIPS" (millions of instructions
  1293. Xper  second);  using  a value such as the number of  register  operators per
  1294. Xsecond in C might give rise to a "MOPS" measurement of more use  to  C  pro-
  1295. Xgrammers.   Those of us who have tried these benchmarks have appreciated the
  1296. Xintuitive grasp that they give of the speed of  current  machines  and  com-
  1297. Xpilers.  I hope that you too will find them of interest.
  1298. X
  1299. X
  1300. X
  1301. X
  1302. X
  1303. X
  1304. X
  1305. END-of-ARTICLE
  1306. exit
  1307. -- 
  1308.       Eric S. Raymond = eric@snark.uu.net    (mad mastermind of TMN-Netnews)
  1309.  
  1310.  
  1311. -- 
  1312. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  1313. Use a domain-based address or give alternate paths, or you may lose out.
  1314.