home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / plum-benchmarks < prev    next >
Text File  |  1989-10-22  |  40KB  |  1,307 lines

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