1 /* dhrystone - benchmark program */
6 * "DHRYSTONE" Benchmark Program
8 * Version: C/1.1, 12/01/84
10 * Date: PROGRAM updated 01/06/86, COMMENTS changed 01/31/87
12 * Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg.1013
13 * Translated from ADA by Rick Richardson
14 * Every method to preserve ADA-likeness has been used,
15 * at the expense of C-ness.
17 * Compile: cc -O dry.c -o drynr : No registers
18 * cc -O -DREG=register dry.c -o dryr : Registers
20 * Defines: Defines are provided for old C compiler's
21 * which don't have enums, and can't assign structures.
22 * The time(2) function is library dependant; Most
23 * return the time in seconds, but beware of some, like
24 * Aztec C, which return other units.
25 * The LOOPS define is initially set for 50000 loops.
26 * If you have a machine with large integers and is
27 * very fast, please change this number to 500000 to
28 * get better accuracy. Please select the way to
29 * measure the execution time using the TIME define.
30 * For single user machines, time(2) is adequate. For
31 * multi-user machines where you cannot get single-user
32 * access, use the times(2) function. Be careful to
33 * adjust the HZ parameter below for the units which
34 * are returned by your times(2) function. You can
35 * sometimes find this in <sys/param.h>. If you have
36 * neither time(2) nor times(2), use a stopwatch in
37 * the dead of the night.
38 * Use a "printf" at the point marked "start timer"
39 * to begin your timings. DO NOT use the UNIX "time(1)"
40 * command, as this will measure the total time to
41 * run this program, which will (erroneously) include
42 * the time to malloc(3) storage and to compute the
43 * time it takes to do nothing.
47 * Results: If you get any new machine/OS results, please send to:
49 * ihnp4!castor!pcrat!rick
51 * and thanks to all that do.
53 * Note: I order the list in increasing performance of the
54 * "with registers" benchmark. If the compiler doesn't
55 * provide register variables, then the benchmark
56 * is the same for both REG and NOREG.
58 * PLEASE: Send complete information about the machine type,
59 * clock speed, OS and C manufacturer/version. If
60 * the machine is modified, tell me what was done.
61 * On UNIX, execute uname -a and cc -V to get this info.
63 * 80x8x NOTE: 80x8x benchers: please try to do all memory models
64 * for a particular compiler.
67 * The following program contains statements of a high-level programming
68 * language (C) in a distribution considered representative:
71 * control statements 32%
72 * procedure, function calls 15%
74 * 100 statements are dynamically executed. The program is balanced with
75 * respect to the three aspects:
77 * - operand type (for simple data types)
79 * operand global, local, parameter, or constant.
81 * The combination of these three aspects is balanced only approximately.
83 * The program does not compute anything meaningfull, but it is
84 * syntactically and semantically correct.
89 #include <sys/types.h>
97 /* Accuracy of timings and human fatigue controlled by next two lines */
98 /*#define LOOPS 50000 */ /* Use this for slow or 16 bit machines */
99 /*#define LOOPS 500000 */ /* Use this for faster machines */
100 /*#define LOOPS (sizeof(int) == 2 ? 50000 : 1000000)*/
105 /* Compiler dependent options */
106 #define NOENUM /* Define if compiler has no enum's */
107 /* #define NOSTRUCTASSIGN */ /* Define if compiler can't assign structures*/
110 /* Define only one of the next two defines */
111 #define TIMES /* Use times(2) time function */
112 /*#define TIME */ /* Use time(2) time function */
116 /* Ganularity of time(2) is of course 1 second */
121 /* Define the granularity of your times(2) function */
122 /*#define HZ 50 */ /* times(2) returns 1/50 second (europe?) */
123 /*#define HZ 60 */ /* times(2) returns 1/60 second (most) */
124 /*#define HZ 100 */ /* times(2) returns 1/100 second (WECo) */
127 /* For compatibility with goofed up version */
128 /*#undef GOOF */ /* Define if you want the goofed up version */
132 char Version
[] = "1.0";
134 char Version
[] = "1.1";
138 #ifdef NOSTRUCTASSIGN
139 #define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
141 #define structassign(d, s) d = s
151 typedef int Enumeration
;
154 Ident1
, Ident2
, Ident3
, Ident4
, Ident5
158 typedef int OneToThirty
;
159 typedef int OneToFifty
;
160 typedef char CapitalLetter
;
161 typedef char String30
[31];
162 typedef int Array1Dim
[51];
163 typedef int Array2Dim
[51][51];
166 struct Record
*PtrComp
;
168 Enumeration EnumComp
;
173 typedef struct Record RecordType
;
174 typedef RecordType
*RecordPtr
;
191 #include <sys/times.h>
195 void prep_timer(void);
196 void timeout(int sig
);
198 void Proc1(RecordPtr PtrParIn
);
199 void Proc2(OneToFifty
*IntParIO
);
200 void Proc3(RecordPtr
*PtrParOut
);
203 void Proc6(Enumeration EnumParIn
, Enumeration
*EnumParOut
);
204 void Proc7(OneToFifty IntParI1
, OneToFifty IntParI2
, OneToFifty
206 void Proc8(Array1Dim Array1Par
, Array2Dim Array2Par
, OneToFifty
207 IntParI1
, OneToFifty IntParI2
);
208 boolean
Func2(String30 StrParI1
, String30 StrParI2
);
209 boolean
Func3(Enumeration EnumParIn
);
211 Enumeration
Func1(int CharPar1
, int CharPar2
);
229 signal(SIGALRM
, timeout
);
244 Array1Dim Array1Glob
;
245 Array2Dim Array2Glob
;
247 RecordPtr PtrGlbNext
;
253 REG OneToFifty IntLoc2
;
259 register unsigned long i
;
260 unsigned long starttime
;
261 unsigned long benchtime
;
262 unsigned long nulltime
;
263 unsigned long nullloops
;
264 unsigned long benchloops
;
265 unsigned long ticks_per_sec
;
271 #define ticks_per_sec HZ
273 ticks_per_sec
= sysconf(_SC_CLK_TCK
);
280 starttime
= time((long *) 0);
285 starttime
= tms
.tms_utime
;
292 nulltime
= time((long *) 0) - starttime
; /* Computes o'head of loop */
297 nulltime
= tms
.tms_utime
- starttime
; /* Computes overhead of looping */
303 PtrGlbNext
= (RecordPtr
) malloc(sizeof(RecordType
));
304 PtrGlb
= (RecordPtr
) malloc(sizeof(RecordType
));
305 PtrGlb
->PtrComp
= PtrGlbNext
;
306 PtrGlb
->Discr
= Ident1
;
307 PtrGlb
->EnumComp
= Ident3
;
308 PtrGlb
->IntComp
= 40;
309 strcpy(PtrGlb
->StringComp
, "DHRYSTONE PROGRAM, SOME STRING");
311 strcpy(String1Loc
, "DHRYSTONE PROGRAM, 1'ST STRING"); /* GOOF */
314 Array2Glob
[8][7] = 10; /* Was missing in published program */
324 starttime
= time((long *) 0);
329 starttime
= tms
.tms_utime
;
339 strcpy(String2Loc
, "DHRYSTONE PROGRAM, 2'ND STRING");
341 BoolGlob
= !Func2(String1Loc
, String2Loc
);
342 while (IntLoc1
< IntLoc2
) {
343 IntLoc3
= 5 * IntLoc1
- IntLoc2
;
344 Proc7(IntLoc1
, IntLoc2
, &IntLoc3
);
347 Proc8(Array1Glob
, Array2Glob
, IntLoc1
, IntLoc3
);
349 for (CharIndex
= 'A'; CharIndex
<= Char2Glob
; ++CharIndex
)
350 if (EnumLoc
== Func1(CharIndex
, 'C'))
351 Proc6(Ident1
, &EnumLoc
);
352 IntLoc3
= IntLoc2
* IntLoc1
;
353 IntLoc2
= IntLoc3
/ IntLoc1
;
354 IntLoc2
= 7 * (IntLoc3
- IntLoc2
) - IntLoc1
;
365 benchtime
= time((long *) 0) - starttime
;
370 benchtime
= tms
.tms_utime
- starttime
;
374 /* Approximately correct benchtime to the nulltime. */
375 benchtime
-= nulltime
/ (nullloops
/ benchloops
);
377 printf("Dhrystone(%s) time for %lu passes = %lu.%02lu\n",
379 benchloops
, benchtime
/ ticks_per_sec
,
380 benchtime
% ticks_per_sec
* 100 / ticks_per_sec
);
381 printf("This machine benchmarks at %lu dhrystones/second\n",
382 benchloops
* ticks_per_sec
/ benchtime
);
387 REG RecordPtr PtrParIn
;
389 #define NextRecord (*(PtrParIn->PtrComp))
392 structassign(NextRecord
, *PtrGlb
);
393 PtrParIn
->IntComp
= 5;
394 NextRecord
.IntComp
= PtrParIn
->IntComp
;
395 NextRecord
.PtrComp
= PtrParIn
->PtrComp
;
396 Proc3((RecordPtr
*)NextRecord
.PtrComp
);
397 if (NextRecord
.Discr
== Ident1
) {
398 NextRecord
.IntComp
= 6;
399 Proc6(PtrParIn
->EnumComp
, &NextRecord
.EnumComp
);
400 NextRecord
.PtrComp
= PtrGlb
->PtrComp
;
401 Proc7(NextRecord
.IntComp
, 10, &NextRecord
.IntComp
);
403 structassign(*PtrParIn
, NextRecord
);
411 OneToFifty
*IntParIO
;
413 REG OneToFifty IntLoc
;
414 REG Enumeration EnumLoc
;
417 IntLoc
= *IntParIO
+ 10;
419 if (Char1Glob
== 'A') {
421 *IntParIO
= IntLoc
- IntGlob
;
424 if (EnumLoc
== Ident1
) break;
429 void Proc3(PtrParOut
)
430 RecordPtr
*PtrParOut
;
433 *PtrParOut
= PtrGlb
->PtrComp
;
436 Proc7(10, IntGlob
, &PtrGlb
->IntComp
);
445 BoolLoc
= Char1Glob
== 'A';
458 void Proc6(EnumParIn
, EnumParOut
)
459 REG Enumeration EnumParIn
;
460 REG Enumeration
*EnumParOut
;
462 *EnumParOut
= EnumParIn
;
463 if (!Func3(EnumParIn
)) *EnumParOut
= Ident4
;
465 case Ident1
: *EnumParOut
= Ident1
; break;
468 *EnumParOut
= Ident1
;
470 *EnumParOut
= Ident4
;
472 case Ident3
: *EnumParOut
= Ident2
; break;
475 case Ident5
: *EnumParOut
= Ident3
;
480 void Proc7(IntParI1
, IntParI2
, IntParOut
)
483 OneToFifty
*IntParOut
;
485 REG OneToFifty IntLoc
;
488 IntLoc
= IntParI1
+ 2;
489 *IntParOut
= IntParI2
+ IntLoc
;
493 void Proc8(Array1Par
, Array2Par
, IntParI1
, IntParI2
)
499 REG OneToFifty IntLoc
;
500 REG OneToFifty IntIndex
;
503 IntLoc
= IntParI1
+ 5;
504 Array1Par
[IntLoc
] = IntParI2
;
505 Array1Par
[IntLoc
+ 1] = Array1Par
[IntLoc
];
506 Array1Par
[IntLoc
+ 30] = IntLoc
;
507 for (IntIndex
= IntLoc
; IntIndex
<= (IntLoc
+ 1); ++IntIndex
)
508 Array2Par
[IntLoc
][IntIndex
] = IntLoc
;
509 ++Array2Par
[IntLoc
][IntLoc
- 1];
510 Array2Par
[IntLoc
+ 20][IntLoc
] = Array1Par
[IntLoc
];
515 Enumeration
Func1(CharPar1
, CharPar2
)
516 CapitalLetter CharPar1
;
517 CapitalLetter CharPar2
;
519 REG CapitalLetter CharLoc1
;
520 REG CapitalLetter CharLoc2
;
525 if (CharLoc2
!= CharPar2
)
532 boolean
Func2(StrParI1
, StrParI2
)
536 REG OneToThirty IntLoc
;
537 REG CapitalLetter CharLoc
;
542 if (Func1(StrParI1
[IntLoc
], StrParI2
[IntLoc
+ 1]) == Ident1
) {
546 if (CharLoc
>= 'W' && CharLoc
<= 'Z') IntLoc
= 7;
550 if (strcmp(StrParI1
, StrParI2
) > 0) {
559 boolean
Func3(EnumParIn
)
560 REG Enumeration EnumParIn
;
562 REG Enumeration EnumLoc
;
566 if (EnumLoc
== Ident3
) return(TRUE
);
571 #ifdef NOSTRUCTASSIGN
577 while (l
--) *d
++ = *s
++;