├── v2.0 ├── _README ├── submit.frm ├── Makefile ├── README.RER ├── dhry_pack_2.c ├── dhry_pack_1.c ├── README └── dhry_global.h ├── v2.1 ├── _README ├── submit.frm ├── d_pack_1.s ├── d_main.b ├── Makefile ├── dhry_c.dif ├── d_pack_2.s ├── README ├── clarify.doc ├── pure2_1.dif ├── README.RER ├── d_pack_2.b ├── dhry_2.c ├── d_pack_1.b ├── dhry_1.c ├── d_global.s └── RATIONALE ├── README.md ├── v1 ├── pack_1.ads ├── _README ├── main.adb ├── pack_2.ads ├── pack_2.adb ├── pack_1.adb ├── user-guide.txt └── global_def.ads └── original-sources ├── README ├── 1988-03-08-dhrystone-2.0-1of3 └── 1984-11-15-dhrystone-part1 /v2.0/_README: -------------------------------------------------------------------------------- 1 | Extracted from a series of articles posted to comp.arch by Rick 2 | Richardson, 1988-03-08 3 | 4 | Pascal and C version 2.0 (no Ada version) 5 | 6 | -------------------------------------------------------------------------------- /v2.1/_README: -------------------------------------------------------------------------------- 1 | Extracted from a series of articles posted to alt.sources from TU 2 | Vienna EDP-Center, Vienna, Austria, 1990-02-14 3 | Pascal and C version 2.1 (no Ada version) 4 | 5 | Combined with http://www.netlib.org/benchmark/dhry-ada 6 | Ada version 2.1 7 | -------------------------------------------------------------------------------- /v2.0/submit.frm: -------------------------------------------------------------------------------- 1 | DHRYSTONE 2.0 BENCHMARK REPORTING FORM 2 | MANUF: 3 | MODEL: 4 | PROC: 5 | CLOCK: 6 | OS: 7 | OVERSION: 8 | COMPILER: 9 | CVERSION: 10 | OPTIONS: 11 | NOREG: 12 | REG: 13 | NOTES: 14 | DATE: 15 | SUBMITTER: 16 | MAILTO: uunet!pcrat!dry2 17 | -------------------------------------------------------------------------------- /v2.1/submit.frm: -------------------------------------------------------------------------------- 1 | DHRYSTONE 2.1 BENCHMARK REPORTING FORM 2 | MANUF: 3 | MODEL: 4 | PROC: 5 | CLOCK: 6 | OS: 7 | OVERSION: 8 | COMPILER: 9 | CVERSION: 10 | OPTIONS: 11 | NOREG: 12 | REG: 13 | NOTES: 14 | DATE: 15 | SUBMITTER: 16 | CODESIZE: 17 | MAILTO: uunet!pcrat!dry2 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Multiple versions of Reinhold P. Weicker's **Dhrystone** benchmark 2 | 3 | Sources downloaded and extracted from old Usenet postings and from 4 | sites linked from http://en.wikipedia.org/wiki/Dhrystone 5 | 6 | The `original-sources` directory contains the raw sources. Each 7 | subdirectory `v1`, `v2.0`, `v2.1`, `v2.2` contains an extracted 8 | version; see the `_README` file in each directory. 9 | -------------------------------------------------------------------------------- /v1/pack_1.ads: -------------------------------------------------------------------------------- 1 | 2 | 3 | with Global_Def; 4 | use Global_Def; 5 | 6 | package Pack_1 is 7 | -------------- 8 | 9 | procedure Proc_0; 10 | procedure Proc_1 (Pointer_Par_In: in Record_Pointer); 11 | procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty); 12 | procedure Proc_3 (Pointer_Par_Out: out Record_Pointer); 13 | 14 | Int_Glob: integer; 15 | 16 | end Pack_1; 17 | -------------------------------------------------------------------------------- /v1/_README: -------------------------------------------------------------------------------- 1 | Extracted from a series of articles posted to net.sources, probably 2 | by Reinhold P. Weicker, 1984-11-15. See user-guide.txt for details. 3 | 4 | dhry-ref-all.a 5 | Ada reference version 6 | dhry-mea.p 7 | Pascal "Measurement Version" 8 | dhry-mea-all.c 9 | C "Measurement Version" 10 | 11 | global_def.ads 12 | main.adb 13 | pack_1.adb 14 | pack_1.ads 15 | pack_2.adb 16 | pack_2.ads 17 | Result of "gnatchop dhry-ref-all.a" 18 | -------------------------------------------------------------------------------- /v1/main.adb: -------------------------------------------------------------------------------- 1 | 2 | 3 | with Global_Def, Pack_1; 4 | use Global_Def; 5 | 6 | procedure Main is 7 | -------------- 8 | 9 | begin 10 | 11 | Pack_1.Proc_0; -- Proc_0 is actually the main program, but it is part 12 | -- of a package, and a program within a package can 13 | -- not be designated as the main program for execution. 14 | -- Therefore Proc_0 is activated by a call from "Main". 15 | 16 | end Main; 17 | -------------------------------------------------------------------------------- /v1/pack_2.ads: -------------------------------------------------------------------------------- 1 | 2 | 3 | with Global_Def; 4 | use Global_Def; 5 | 6 | package Pack_2 is 7 | -------------- 8 | 9 | procedure Proc_6 (Enum_Par_In: in Enumeration; 10 | Enum_Par_Out: out Enumeration); 11 | procedure Proc_7 (Int_Par_In_1, 12 | Int_Par_In_2: in One_To_Fifty; 13 | Int_Par_Out: out One_To_Fifty); 14 | procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer; 15 | Array_Par_In_Out_2: in out Array_2_Dim_Integer; 16 | Int_Par_In_1, 17 | Int_Par_In_2: in integer); 18 | function Func_1 (Char_Par_In_1, 19 | Char_Par_In_2: in Capital_Letter) 20 | return Enumeration; 21 | function Func_2 (String_Par_In_1, 22 | String_Par_In_2: in String_30) 23 | return boolean; 24 | 25 | end Pack_2; 26 | -------------------------------------------------------------------------------- /v2.1/d_pack_1.s: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- 8 | -- File: d_pack_1.s (part 2 of 6) 9 | -- 10 | -- Date: August 17, 1988 11 | -- 12 | -- Author: Reinhold P. Weicker 13 | -- 14 | ------------------------------------------------------------------------ 15 | 16 | with Global_Def; 17 | use Global_Def; 18 | 19 | package Pack_1 is 20 | -------------- 21 | 22 | procedure Proc_0; 23 | procedure Proc_1 (Pointer_Par_In: in Record_Pointer); 24 | procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty); 25 | procedure Proc_3 (Pointer_Par_Out: out Record_Pointer); 26 | 27 | Int_Glob: integer; 28 | Char_Glob_1: character; 29 | 30 | end Pack_1; 31 | 32 | 33 | -------------------------------------------------------------------------------- /v2.1/d_main.b: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- 8 | -- File: d_main.b (part 6 of 6) 9 | -- 10 | -- Date: August 17, 1988 11 | -- 12 | -- Author: Reinhold P. Weicker 13 | -- 14 | ------------------------------------------------------------------------ 15 | 16 | with Global_Def, Pack_1; 17 | use Global_Def; 18 | 19 | procedure Main is 20 | -------------- 21 | 22 | begin 23 | 24 | Pack_1.Proc_0; -- Proc_0 is actually the main program, but it is part 25 | -- of a package, and a program within a package can 26 | -- not be designated as the main program for execution. 27 | -- Therefore Proc_0 is activated by a call from "Main". 28 | 29 | end Main; 30 | 31 | -------------------------------------------------------------------------------- /v2.1/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = 2 | TIME = time 3 | 4 | all: rundhrystone rundhrystoneR rundhrystoneO rundhrystoneRO 5 | 6 | dhrystone: dhrystone.c 7 | $(CC) dhrystone.c -o dhrystone 8 | 9 | rundhrystone: dhrystone 10 | @echo 'Running dhrystone (Level 1 optimization, without registers)' 11 | ./dhrystone 12 | ./dhrystone 13 | ./dhrystone 14 | @echo 15 | 16 | 17 | dhrystoneR: dhrystone.c 18 | $(CC) -DREG=register dhrystone.c -o dhrystoneR 19 | 20 | rundhrystoneR: dhrystoneR 21 | @echo 'Running dhrystone (Level 1 optimization, with registers)' 22 | ./dhrystoneR 23 | ./dhrystoneR 24 | ./dhrystoneR 25 | @echo 26 | 27 | 28 | dhrystoneO: dhrystone.c 29 | $(CC) -O dhrystone.c -o dhrystoneO 30 | 31 | rundhrystoneO: dhrystoneO 32 | @echo 'Running dhrystone (Level 2 optimization, without registers)' 33 | ./dhrystoneO 34 | ./dhrystoneO 35 | ./dhrystoneO 36 | @echo 37 | 38 | 39 | dhrystoneRO: dhrystone.c 40 | $(CC) -O -DREG=register dhrystone.c -o dhrystoneRO 41 | 42 | rundhrystoneRO: dhrystoneRO 43 | @echo 'Running dhrystone (Level 2 optimization, with registers)' 44 | ./dhrystoneRO 45 | ./dhrystoneRO 46 | ./dhrystoneRO 47 | @echo 48 | 49 | 50 | clean: 51 | (set nonomatch;rm -f dhrystone dhrystoneR dhrystoneO dhrystoneRO *.o) 52 | -------------------------------------------------------------------------------- /v2.1/dhry_c.dif: -------------------------------------------------------------------------------- 1 | 7c7 2 | < * Version: C, Version 2.1 3 | --- 4 | > * Version: C, Version 2.0 5 | 11c11 6 | < * Date: May 17, 1988 7 | --- 8 | > * Date: March 3, 1988 9 | 50,51d49 10 | < #define Too_Small_Time 120 11 | < /* Measurements should last at least about 2 seconds */ 12 | 55a54,58 13 | > #endif 14 | > #ifdef MSC_TIME 15 | > clock_t clock(); 16 | > #endif 17 | > 18 | 58d60 19 | < #endif 20 | 73a76 21 | > 22 | 84a88 23 | > 24 | 99,100c103,105 25 | < /* Was missing in published program. Without this statement, */ 26 | < /* Arr_2_Glob [8][7] would have an undefined value. */ 27 | --- 28 | > /* Was missing in published program. Without this */ 29 | > /* initialization, Arr_2_Glob [8][7] would have an */ 30 | > /* undefined value. */ 31 | 105c110 32 | < printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); 33 | --- 34 | > printf ("Dhrystone Benchmark, Version 2.0 (Language: C)\n"); 35 | 134a140,142 36 | > #ifdef MSC_CLOCK 37 | > Begin_Time = clock(); 38 | > #endif 39 | 192a201,203 40 | > #ifdef MSC_CLOCK 41 | > End_Time = clock(); 42 | > #endif 43 | 281c292 44 | < /******************/ 45 | --- 46 | > /**********************/ 47 | 338c349 48 | < /******************/ 49 | --- 50 | > /**********************/ 51 | 347a359,360 52 | > else /* not executed */ 53 | > Int_Glob = 100; 54 | 351a365 55 | > 56 | 384,385d397 57 | < 58 | < 59 | -------------------------------------------------------------------------------- /v2.0/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Adjust for your system 3 | # 4 | # TIME_FUNC, STRUCTASSIGN, and ENUMS selectable by changing order 5 | # 6 | CC= cc # C compiler name goes here 7 | 8 | TIME_FUNC= -DTIME # Use time(2) for measurement 9 | TIME_FUNC= -DTIMES # Use times(2) for measurement 10 | HZ= 60 # Frequency of times(2) clock ticks 11 | 12 | STRUCTASSIGN= -DNOSTRUCTASSIGN # Compiler cannot assign structs 13 | STRUCTASSIGN= # Compiler can assign structs 14 | 15 | ENUMS= -DNOENUMS # Compiler doesn't have enum type 16 | ENUMS= # Compiler does have enum type 17 | 18 | OPTIMIZE= -O # Optimization Level 19 | 20 | LFLAGS= #Loader Flags 21 | 22 | CFLAGS= $(OPTIMIZE) $(TIME_FUNC) -DHZ=$(HZ) $(ENUMS) $(STRUCTASSIGN) $(CFL) 23 | 24 | # 25 | # You shouldn't need to touch the rest 26 | # 27 | SRC= dhry_pack_1.c dhry_pack_2.c 28 | HDR= dhry_global.h 29 | 30 | all: dry2 dry2reg 31 | 32 | dry2: $(SRC) $(HDR) 33 | $(CC) $(CFLAGS) $(SRC) $(LFLAGS) -o $@ 34 | 35 | dry2reg: $(SRC) $(HDR) 36 | $(CC) $(CFLAGS) -DREG=register $(SRC) $(LFLAGS) -o $@ 37 | 38 | shar: dry2shar.1 dry2shar.2 dry2shar.3 39 | 40 | dry2shar.1: README.RER Makefile submit.frm 41 | shar -p X README.RER Makefile submit.frm >$@ 42 | 43 | dry2shar.2: README $(HDR) $(SRC) 44 | shar -p X README $(HDR) $(SRC) >$@ 45 | 46 | dry2shar.3: dhry.p 47 | shar -p X dhry.p >$@ 48 | 49 | clean: 50 | -rm -f *.o 51 | 52 | clobber: clean 53 | -rm -f dry2 dry2reg dry2shar.* 54 | 55 | post: 56 | for i in 1 2 3;\ 57 | do\ 58 | cat HEADERS BOILER.$$i dry2shar.$$i |\ 59 | inews -h -t "Dhrystone 2.0 ($$i of 3)" -n comp.arch;\ 60 | done 61 | -------------------------------------------------------------------------------- /v2.1/d_pack_2.s: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- 8 | -- File: d_pack_2.s (part 3 of 6) 9 | -- 10 | -- Date: August 17, 1988 11 | -- 12 | -- Author: Reinhold P. Weicker 13 | -- 14 | ------------------------------------------------------------------------ 15 | 16 | with Global_Def; 17 | use Global_Def; 18 | 19 | package Pack_2 is 20 | -------------- 21 | 22 | procedure Proc_6 (Enum_Par_In: in Enumeration; 23 | Enum_Par_Out: out Enumeration); 24 | procedure Proc_7 (Int_Par_In_1, 25 | Int_Par_In_2: in One_To_Fifty; 26 | Int_Par_Out: out One_To_Fifty); 27 | procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer; 28 | Array_Par_In_Out_2: in out Array_2_Dim_Integer; 29 | Int_Par_In_1, 30 | Int_Par_In_2: in integer); 31 | function Func_1 (Char_Par_In_1, 32 | Char_Par_In_2: in Capital_Letter) 33 | return Enumeration; 34 | function Func_2 (String_Par_In_1, 35 | String_Par_In_2: in String_30) 36 | return boolean; 37 | 38 | end Pack_2; 39 | 40 | 41 | -------------------------------------------------------------------------------- /original-sources/README: -------------------------------------------------------------------------------- 1 | Reference: http://en.wikipedia.org/wiki/Dhrystone 2 | 3 | 1984-11-15-dhrystone-part1 4 | 1984-11-15-dhrystone-part2 5 | 1984-11-15-dhrystone-part3 6 | 1984-11-15-dhrystone-part4 7 | Posted to net.sources, probably by Reinhold P. Weicker, 1984-11-15 8 | Dhrystone version 1 (Ada only), plus C and Pascal "version 2" 9 | Message-ID: <28600001@siemens.UUCP> 10 | Message-ID: <28600005@siemens.UUCP> 11 | Message-ID: <28600006@siemens.UUCP> 12 | Message-ID: <28600007@siemens.UUCP> 13 | 14 | 1986-10-03-dhrystone-ada 15 | Posted to net.lang.ada and net.sources by Bob Bentley, 1986-10-03 16 | Dhrystone version 1 repost 17 | Message-ID: <155@omepd> 18 | No significant changes from 1984 posting (some whitespace changes 19 | and one paragraph of comments is formatted differently) 20 | I haven't checked this version into git 21 | 22 | 1988-03-08-dhrystone-2.0-1of3 23 | 1988-03-08-dhrystone-2.0-2of3 24 | 1988-03-08-dhrystone-2.0-3of3 25 | Posted to comp.arch by Rick Richardson, 1988-03-08 26 | Pascal and C, version 2.0 27 | Message-ID: <492@pcrat.UUCP> 28 | Message-ID: <493@pcrat.UUCP> 29 | Message-ID: <494@pcrat.UUCP> 30 | 31 | 1990-02-14-dhrystone-part1 32 | 1990-02-14-dhrystone-part2 33 | 1990-02-14-dhrystone-part3 34 | 1990-02-14-dhrystone-part4 35 | Posted to alt.sources from TU Vienna EDP-Center, Vienna, Austria, 1990-02-14 36 | Pascal and C, version 2.1 37 | Message-ID: <1101@tuvie> 38 | Message-ID: <1102@tuvie> 39 | Message-ID: <1103@tuvie> 40 | Message-ID: <1104@tuvie> 41 | 42 | dhry-c 43 | Linked from the Wikipedia article: 44 | http://www.netlib.org/benchmark/dhry-c 45 | Dated 1990-08-25 46 | C, version 2.1 47 | 48 | dhry-ada 49 | http://www.netlib.org/benchmark/dhry-ada 50 | Dated 1990-08-25 51 | Ada, version 2.1 52 | 53 | dhry-pascal 54 | http://www.netlib.org/benchmark/dhry-pascal 55 | Dated 1990-08-25 56 | Pascal, version 2.1 57 | 58 | dry.c 59 | Linked from the Wikipedia article: 60 | http://homepages.cwi.nl/~steven/dry.c 61 | Dated 1996-03-08 62 | C, version 2.2 63 | -------------------------------------------------------------------------------- /v2.0/README.RER: -------------------------------------------------------------------------------- 1 | Since I was flooded with requests to not wait a day, let alone a week 2 | before posting Dhrystone 2.0, here it is, without any delay (and no 3 | results, either). 4 | 5 | I've enclosed a new submission form (note new address for mailings). 6 | Please deluge this mailbox (..!uunet!pcrat!dry2) with your results. 7 | I'll summarize and repost when the dust clears. Please do not 8 | assume that I will pull posted results off of the net (I won't, its 9 | too much work). 10 | 11 | Also, please make note of the fact that I've attempted to include 12 | a Makefile for UNIX. Pay particular attention to the HZ parameter, 13 | even though your power may be 50 or 60 hertz, your computer may not be. 14 | You may have to ask someone, read the manual, or check 15 | /usr/include/sys/param.h 16 | for this information. 17 | 18 | There are two versions to run, one with register variables, and one 19 | without. Please let the benchmark run for 30,000 loops on sixteen 20 | bit machines, and for much longer (a minute or two) on faster machines. 21 | For segmented architectures, it is appropriate to submit results for 22 | all memory models, as shown below. 23 | 24 | Here's a sample submission of results: 25 | 26 | DHRYSTONE 2.0 BENCHMARK REPORTING FORM 27 | MANUF: IBM 28 | MODEL: PC/AT 29 | PROC: 80286 30 | CLOCK: 8 Mhz 31 | OS: Venix 32 | OVERSION: SVr2.3 33 | COMPILER: AT&T cc 34 | CVERSION: 11/8/84 35 | OPTIONS: -O 36 | NOREG: 1318 37 | REG: 1450 38 | NOTES: Small Model 39 | DATE: 03/04/88 40 | SUBMITTER: pcrat!rick (Rick Richardson) 41 | MAILTO: uunet!pcrat!dry2 42 | 43 | DHRYSTONE 2.0 BENCHMARK REPORTING FORM 44 | MANUF: IBM 45 | MODEL: PC/AT 46 | PROC: 80286 47 | CLOCK: 8 Mhz 48 | OS: Venix 49 | OVERSION: SVr2.3 50 | COMPILER: AT&T cc 51 | CVERSION: 11/8/84 52 | OPTIONS: -O -Ml 53 | NOREG: 1043 54 | REG: 1043 55 | NOTES: Large Model 56 | DATE: 03/04/88 57 | SUBMITTER: pcrat!rick (Rick Richardson) 58 | MAILTO: uunet!pcrat!dry2 59 | 60 | 61 | Rick Richardson, President, PC Research, Inc. 62 | 63 | (201) 542-3734 (voice, nights) OR (201) 834-1378 (voice, days) 64 | uunet!pcrat!rick (UUCP) rick%pcrat.u...@uunet.uu.net (INTERNET) 65 | uunet!pcrat!dry2 (Dhrystone submission forms only) 66 | -------------------------------------------------------------------------------- /v2.1/README: -------------------------------------------------------------------------------- 1 | This floppy disk contains the source code of the Dhrystone benchmark 2 | (version 2.1) in three languages: 3 | 4 | Files containing the Ada version (*.s: Specifications, *.b: Bodies): 5 | 6 | d_global.s 7 | d_main.b 8 | d_pack_1.b 9 | d_pack_1.s 10 | d_pack_2.b 11 | d_pack_2.s 12 | 13 | (The file names have been abbreviated to 8 characters plus extension 14 | for MS-DOS) 15 | 16 | Files containing the C version (*.h: Header File, *.c: C Modules) 17 | 18 | dhry.h 19 | dhry_1.c 20 | dhry_2.c 21 | 22 | File containing the Pascal version: 23 | 24 | dhry.p 25 | 26 | The file RATIONALE contains the article 27 | 28 | "Dhrystone Benchmark: Rationale for Version 2 and Measurement Rules" 29 | 30 | which has been published, together with the C source code (Version 2.0), 31 | in SIGPLAN Notices vol. 23, no. 8 (Aug. 1988), pp. 49-62. 32 | This article explains all changes that have been made for Version 2, 33 | compared with the version of the original publication 34 | in Communications of the ACM vol. 27, no. 10 (Oct. 1984), pp. 1013-1030. 35 | It also contains "ground rules" for benchmarking with Dhrystone 36 | which should be followed by everyone who uses the program and publishes 37 | Dhrystone results. 38 | 39 | Compared with the Version 2.0 published in SIGPLAN Notices, Version 2.1 40 | contains a few corrections that have been made after Version 2.0 was 41 | distriobuted over the UNIX network Usenet. These small differences between 42 | Version 2.0 and 2.1 should not affect execution time measurements. 43 | For those who want to compare the exact contents of both versions, 44 | the file "dhry_c.dif" contains the differences between the two versions, 45 | as generated by a file comparison of the corresponding files with the 46 | UNIX utility "diff". 47 | 48 | Recipients of this floppy disk who perform measurements are asked 49 | to send measurement results to the author and/or to Rick Richardson. 50 | Rick Richardson publishes regularly Dhrystone results on the UNIX network 51 | Usenet. For submissions of results to him (preferably by electronic mail, 52 | see address in the program header), he has provided a form which is contained 53 | in the file "submit.frm". 54 | 55 | August 17, 1988 56 | 57 | Reinhold P. Weicker 58 | Siemens AG, E STE 35 59 | Postfach 3240 60 | D-8520 Erlangen 61 | Germany (West) 62 | 63 | Phone: [xxx-49]-9131-7-20330 (8-17 Central European Time) 64 | Usenet: ..!mcvax!unido!estevax!weicker 65 | -------------------------------------------------------------------------------- /v2.1/clarify.doc: -------------------------------------------------------------------------------- 1 | CLARIFICATION 2 | There seems to have been a great deal of confusion over what this 3 | benchmark measures, and how to use these results. Let me try to clarify 4 | this: 5 | 6 | 1) DHRYSTONE is a measure of processor+compiler efficiency in 7 | executing a 'typical' program. The 'typical' program was 8 | designed by measuring statistics on a great number of 9 | 'real' programs. The 'typical' program was then written 10 | by Reinhold P. Weicker using these statistics. The 11 | program is balanced according to statement type, as well 12 | as data type. 13 | 14 | 2) DHRYSTONE does not use floating point. Typical programs don't. 15 | 16 | 3) DHRYSTONE does not do I/O. Typical programs do, but then 17 | we'd have a whole can of worms opened up. 18 | 19 | 4) DHRYSTONE does not contain much code that can be optimized 20 | by vector processors. That is why a CRAY doesn't look real 21 | fast, they weren't built to do this sort of computing. 22 | 23 | 5) DHRYSTONE does not measure OS performance, as it avoids 24 | calling the O.S. The O.S. is indicated in the results only 25 | to help in identifying the compiler technology. 26 | 27 | 6) DHRYSTONE is not perfect, but is a hell of a lot better than 28 | the "sieve", or "SI". 29 | 30 | 7) DHRYSTONE gives results in dhrystones/second. Bigger 31 | numbers are better. As a baseline, the original IBM PC 32 | gives around 300-400 dhrystones/second with a good compiler. 33 | The fastest machines today are approaching 100,000. 34 | 35 | If somebody asked me to pick out the best machine for the money, I 36 | wouldn't look at just the results of DHRYSTONE. I'd probably: 37 | 38 | 1) Run DHRYSTONE to get a feel for the compiler+processor 39 | speed. 40 | 2) Run any number of benchmarks to check disk I/O bandwidth, 41 | using both sequential and random read/writes. 42 | 3) Run a multitasking benchmark to check multi-user response 43 | time. Typically, these benchmarks run several types of 44 | programs such as editors, shell scripts, sorts, compiles, 45 | and plot the results against the number of simulated users. 46 | 4) If appropriate for the intended use, run something like 47 | WHETSTONE, to determine floating point performance. 48 | 5) If appropriate for intended use, run some programs which do 49 | vector and matrix computations. 50 | 6) Figure out what the box will: 51 | - cost to buy 52 | - cost to operate and maintain 53 | - be worth when it is sold 54 | - be worth if the manufacturer goes out of business 55 | 7) Having done the above, I probably have a hand-full of 56 | machines which meet my price/performance requirements. 57 | Now, I find out if the applications programs I'd like 58 | to use will run on any of these machines. I also find 59 | out how much interest people have in writing new software 60 | for the machine, and look carefully at the migration path 61 | I will have to take when I reach the (inevitable) limits 62 | of the machine. 63 | 64 | To summarize, DHRYSTONES by themselves are not anything more than 65 | a way to win free beers when arguing 'Box-A versus Box-B' religion. 66 | They do provide insight into Box-A/Compiler-A versus Box-A/Compiler-B 67 | comparisons. 68 | 69 | Rick Richardson 70 | PC Research, Inc. 71 | (201) 389-8963 (9-17 EST) 72 | (201) 542-3734 (7-9,17-24 EST) 73 | ...!uunet!pcrat!rick (normal mail) 74 | ...!uunet!pcrat!dry2 (results only) 75 | -------------------------------------------------------------------------------- /v2.1/pure2_1.dif: -------------------------------------------------------------------------------- 1 | *** rer/dhry.h Sun Dec 4 00:08:26 1988 2 | --- weicker/dhry.h Sun Dec 4 00:09:00 1988 3 | *************** 4 | *** 38,45 5 | * PC Research. Inc. 6 | * 94 Apple Orchard Drive 7 | * Tinton Falls, NJ 07724 8 | ! * Phone: (201) 389-8963 (9-17 EST) 9 | ! * Usenet: ...!uunet!pcrat!rick 10 | * 11 | * Please send results to Rick Richardson and/or Reinhold Weicker. 12 | * Complete information should be given on hardware and software used. 13 | 14 | --- 38,45 ----- 15 | * PC Research. Inc. 16 | * 94 Apple Orchard Drive 17 | * Tinton Falls, NJ 07724 18 | ! * Phone: (201) 834-1378 (9-17 EST) 19 | ! * Usenet: ...!seismo!uunet!pcrat!rick 20 | * 21 | * Please send results to Rick Richardson and/or Reinhold Weicker. 22 | * Complete information should be given on hardware and software used. 23 | *************** 24 | *** 348,354 25 | /* Compiler and system dependent definitions: */ 26 | 27 | #ifndef TIME 28 | - #undef TIMES 29 | #define TIMES 30 | #endif 31 | /* Use times(2) time function unless */ 32 | 33 | --- 348,353 ----- 34 | /* Compiler and system dependent definitions: */ 35 | 36 | #ifndef TIME 37 | #define TIMES 38 | #endif 39 | /* Use times(2) time function unless */ 40 | *************** 41 | *** 353,366 42 | #endif 43 | /* Use times(2) time function unless */ 44 | /* explicitly defined otherwise */ 45 | - 46 | - #ifdef MSC_CLOCK 47 | - #undef HZ 48 | - #undef TIMES 49 | - #include 50 | - #define HZ CLK_TCK 51 | - #endif 52 | - /* Use Microsoft C hi-res clock */ 53 | 54 | #ifdef TIMES 55 | #include 56 | 57 | --- 352,357 ----- 58 | #endif 59 | /* Use times(2) time function unless */ 60 | /* explicitly defined otherwise */ 61 | 62 | #ifdef TIMES 63 | #include 64 | *** rer/dhry_1.c Sun Dec 4 00:08:36 1988 65 | --- weicker/dhry_1.c Sun Dec 4 00:09:09 1988 66 | *************** 67 | *** 47,53 68 | struct tms time_info; 69 | extern int times (); 70 | /* see library function "times" */ 71 | ! #define Too_Small_Time (2*HZ) 72 | /* Measurements should last at least about 2 seconds */ 73 | #endif 74 | #ifdef TIME 75 | 76 | --- 47,53 ----- 77 | struct tms time_info; 78 | extern int times (); 79 | /* see library function "times" */ 80 | ! #define Too_Small_Time 120 81 | /* Measurements should last at least about 2 seconds */ 82 | #endif 83 | #ifdef TIME 84 | *************** 85 | *** 56,65 86 | #define Too_Small_Time 2 87 | /* Measurements should last at least 2 seconds */ 88 | #endif 89 | - #ifdef MSC_CLOCK 90 | - extern clock_t clock(); 91 | - #define Too_Small_Time (2*HZ) 92 | - #endif 93 | 94 | long Begin_Time, 95 | End_Time, 96 | 97 | --- 56,61 ----- 98 | #define Too_Small_Time 2 99 | /* Measurements should last at least 2 seconds */ 100 | #endif 101 | 102 | long Begin_Time, 103 | End_Time, 104 | *************** 105 | *** 139,147 106 | #ifdef TIME 107 | Begin_Time = time ( (long *) 0); 108 | #endif 109 | - #ifdef MSC_CLOCK 110 | - Begin_Time = clock(); 111 | - #endif 112 | 113 | for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) 114 | { 115 | 116 | --- 135,140 ----- 117 | #ifdef TIME 118 | Begin_Time = time ( (long *) 0); 119 | #endif 120 | 121 | for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) 122 | { 123 | *************** 124 | *** 199,207 125 | #endif 126 | #ifdef TIME 127 | End_Time = time ( (long *) 0); 128 | - #endif 129 | - #ifdef MSC_CLOCK 130 | - End_Time = clock(); 131 | #endif 132 | 133 | printf ("Execution ends\n"); 134 | 135 | --- 192,197 ----- 136 | #endif 137 | #ifdef TIME 138 | End_Time = time ( (long *) 0); 139 | #endif 140 | 141 | printf ("Execution ends\n"); 142 | -------------------------------------------------------------------------------- /v1/pack_2.adb: -------------------------------------------------------------------------------- 1 | 2 | 3 | with Global_Def, Pack_1; 4 | use Global_Def; 5 | 6 | package body Pack_2 is 7 | ------------------- 8 | 9 | function Func_3 (Enum_Par_In: in Enumeration) return boolean; 10 | -- forward declaration 11 | 12 | procedure Proc_6 (Enum_Par_In: in Enumeration; 13 | Enum_Par_Out: out Enumeration) 14 | is -- executed once 15 | -- Enum_Par_In = Ident_3, Enum_Par_Out becomes Ident_2 16 | begin 17 | Enum_Par_Out := Enum_Par_In; 18 | if not Func_3 (Enum_Par_In) 19 | then -- not executed 20 | Enum_Par_Out := Ident_4; 21 | end if; 22 | case Enum_Par_In is 23 | when Ident_1 => Enum_Par_Out := Ident_1; 24 | when Ident_2 => if Pack_1.Int_Glob > 100 25 | then Enum_Par_Out := Ident_1; 26 | else Enum_Par_Out := Ident_4; 27 | end if; 28 | when Ident_3 => Enum_Par_Out := Ident_2; -- executed 29 | when Ident_4 => null; 30 | when Ident_5 => Enum_Par_Out := Ident_3; 31 | end case; 32 | end Proc_6; 33 | 34 | procedure Proc_7 (Int_Par_In_1, 35 | Int_Par_In_2: in One_To_Fifty; 36 | Int_Par_Out: out One_To_Fifty) 37 | is -- executed three times 38 | -- first call: Int_Par_In_1 = 2, Int_Par_In_2 = 3, 39 | -- Int_Par_Out becomes 7 40 | -- second call: Int_Par_In_1 = 6, Int_Par_In_2 = 10, 41 | -- Int_Par_Out becomes 18 42 | -- third call: Int_Par_In_1 = 10, Int_Par_In_2 = 5, 43 | -- Int_Par_Out becomes 17 44 | Int_Loc: One_To_Fifty; 45 | begin 46 | Int_Loc := Int_Par_In_1 + 2; 47 | Int_Par_Out := Int_Par_In_2 + Int_Loc; 48 | end Proc_7; 49 | 50 | procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer; 51 | Array_Par_In_Out_2: in out Array_2_Dim_Integer; 52 | Int_Par_In_1, 53 | Int_Par_In_2: in integer) 54 | is -- executed once 55 | -- Int_Par_In_1 = 3 56 | -- Int_Par_In_2 = 7 57 | Int_Loc: One_To_Fifty; 58 | begin 59 | Int_Loc := Int_Par_In_1 + 5; 60 | Array_Par_In_Out_1 (Int_Loc) := Int_Par_In_2; 61 | Array_Par_In_Out_1 (Int_Loc+1) := 62 | Array_Par_In_Out_1 (Int_Loc); 63 | Array_Par_In_Out_1 (Int_Loc+30) := Int_Loc; 64 | for Int_Index in Int_Loc .. Int_Loc+1 loop -- loop body executed twice 65 | Array_Par_In_Out_2 (Int_Loc, Int_Index) := Int_Loc; 66 | end loop; 67 | Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) := 68 | Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) + 1; 69 | Array_Par_In_Out_2 (Int_Loc+20, Int_Loc) := 70 | Array_Par_In_Out_1 (Int_Loc); 71 | Pack_1.Int_Glob := 5; 72 | end Proc_8; 73 | 74 | function Func_1 (Char_Par_In_1, 75 | Char_Par_In_2: in Capital_Letter) 76 | return Enumeration 77 | is -- executed three times, returns Ident_1 each time 78 | -- first call: Char_Par_In_1 = 'H', Char_Par_In_2 = 'R' 79 | -- second call: Char_Par_In_1 = 'A', Char_Par_In_2 = 'C' 80 | -- third call: Char_Par_In_1 = 'B', Char_Par_In_2 = 'C' 81 | Char_Loc_1, Char_Loc_2: Capital_Letter; 82 | begin 83 | Char_Loc_1 := Char_Par_In_1; 84 | Char_Loc_2 := Char_Loc_1; 85 | if Char_Loc_2 /= Char_Par_In_2 86 | then -- executed 87 | return Ident_1; 88 | else -- not executed 89 | return Ident_2; 90 | end if; 91 | end Func_1; 92 | 93 | function Func_2 (String_Par_In_1, 94 | String_Par_In_2: in String_30) return boolean 95 | is -- executed once, returns false 96 | -- String_Par_In_1 = "DHRYSTONE PROGRAM, 1'ST STRING" 97 | -- String_Par_In_2 = "DHRYSTONE PROGRAM, 2'ND STRING" 98 | Int_Loc: One_To_Thirty; 99 | Char_Loc: Capital_Letter; 100 | begin 101 | Int_Loc := 2; 102 | while Int_Loc <= 2 loop -- loop body executed once 103 | if Func_1 (String_Par_In_1(Int_Loc), 104 | String_Par_In_2(Int_Loc+1)) = Ident_1 105 | then -- executed 106 | Char_Loc := 'A'; 107 | Int_Loc := Int_Loc + 1; 108 | end if; 109 | end loop; 110 | if Char_Loc >= 'W' and Char_Loc < 'Z' 111 | then -- not executed 112 | Int_Loc := 7; 113 | end if; 114 | if Char_Loc = 'X' 115 | then -- not executed 116 | return true; 117 | else -- executed 118 | if String_Par_In_1 > String_Par_In_2 119 | then -- not executed 120 | Int_Loc := Int_Loc + 7; 121 | return true; 122 | else -- executed 123 | return false; 124 | end if; 125 | end if; 126 | end Func_2; 127 | 128 | function Func_3 (Enum_Par_In: in Enumeration) return boolean 129 | is -- executed once, returns true 130 | -- Enum_Par_In = Ident_3 131 | Enum_Loc: Enumeration; 132 | begin 133 | Enum_Loc := Enum_Par_In; 134 | if Enum_Loc = Ident_3 135 | then -- executed 136 | return true; 137 | end if; 138 | end Func_3; 139 | 140 | end Pack_2; 141 | -------------------------------------------------------------------------------- /v2.1/README.RER: -------------------------------------------------------------------------------- 1 | 12/04/88 2 | 3 | Here is Reinhold Weicker's DHRYSTONE 2.1 benchmark, slightly modified 4 | by me for instrumentation purposes only. This is an integer CPU 5 | benchmark. The differences between 2.0 and 2.1 are minor, and 6 | I believe that 2.0 and 2.1 results are comparable. 7 | 8 | For purists, I've enclosed context diffs to turn what I'm posting 9 | as 2.1 back into what Reinhold sent me as 2.1. The changes 10 | are in pure2_1.dif. As you can see, it is only the instrumentation 11 | that is slightly different. 12 | 13 | Both the C and the Pascal versions are here. The Ada version I 14 | have is marked preliminary (not to be posted). 15 | 16 | I've enclosed a new submission form (note new address for mailings). 17 | Please deluge this mailbox (..!uunet!pcrat!dry2) with your results. 18 | I'll summarize and repost when the dust clears. Please do not 19 | assume that I will pull posted results off of the net (I won't, its 20 | too much work). 21 | 22 | I've attempted to include a Makefile for UNIX and Microsoft C (with ndmake). 23 | Pay particular attention to the HZ parameter, even though your power may 24 | be 50 or 60 hertz, your computer may not be. You may have to ask someone, 25 | read the manual, or check: 26 | /usr/include/sys/param.h 27 | /usr/include/limits.h (CLK_TCK==HZ) 28 | for this information. 29 | 30 | REPEAT: HZ IS NOT NECESSARILY THE FREQUENCY OF YOUR AC POWER !!!!!! 31 | 32 | There are two versions to run, one with register variables, and one 33 | without. Please let the benchmark run for 30,000 loops on sixteen 34 | bit machines, and for much longer (a minute or two) on faster machines. 35 | Please note that "time(2)" has a resolution of 1 second, and may give 36 | variable results. No matter how time is measured, a sanity check with 37 | a stopwatch is prudent. We've run into systems that lie about time, 38 | and there is always the configuration error problem. When it comes 39 | to time measurement on UNIX, there is no widely adhered to standard. 40 | 41 | For segmented architectures, it is appropriate to submit results for 42 | all memory models, as shown below. 43 | 44 | I dropped the CODESIZE information that I attempted to add the last 45 | time I posted this. People couldn't follow directions, and the 46 | information wasn't very useful anyway. 47 | 48 | Here's a sample submission of results: 49 | 50 | DHRYSTONE 2.1 BENCHMARK REPORTING FORM 51 | MANUF: IBM 52 | MODEL: PC/AT 53 | PROC: 80286 54 | CLOCK: 8 55 | OS: Venix 56 | OVERSION: SVr2.3 57 | COMPILER: AT&T cc 58 | CVERSION: 11/8/84 59 | OPTIONS: -O 60 | NOREG: 1450 61 | REG: 1450 62 | NOTES: HZ=60; Small Model 63 | DATE: 03/04/88 64 | SUBMITTER: pcrat!rick (Rick Richardson) 65 | MAILTO: uunet!pcrat!dry2 66 | 67 | DHRYSTONE 2.1 BENCHMARK REPORTING FORM 68 | MANUF: IBM 69 | MODEL: PC/AT 70 | PROC: 80286 71 | CLOCK: 8 72 | OS: Venix 73 | OVERSION: SVr2.3 74 | COMPILER: AT&T cc 75 | CVERSION: 11/8/84 76 | OPTIONS: -O -Ml 77 | NOREG: 1043 78 | REG: 1043 79 | NOTES: HZ=60; Large Model 80 | DATE: 03/04/88 81 | SUBMITTER: pcrat!rick (Rick Richardson) 82 | MAILTO: uunet!pcrat!dry2 83 | 84 | The program that processes submission forms is rather dumb. Please 85 | do not change the order, add or removes lines in the form. If your 86 | NOTES are longer than the space provided, then they are too long for 87 | the summary. Keep it terse, please. 88 | 89 | A form consists of all lines between: 90 | DHRYSTONE 2.1 BENCHMARK REPORTING FORM 91 | and 92 | MAILTO: uunet!pcrat!dry2 93 | both lines must be present for the form to be processed. If 94 | a field does not apply or is not known, leave it blank. The fields 95 | are: 96 | MANUF: Computer manufacturer, e.g. AT&T, IBM 97 | MODEL: Model number of computer 98 | PROC: If a microprocessor CPU, the part number, e.g. 68030 99 | CLOCK: Clock in Mhz, if known. Numeric only, e.g. 16.67 100 | OS: Operating system, e.g. UNIX 101 | OVERSION: OS version, e.g. SVR3 102 | COMPILER: Compiler name, e.g. cc, Microsoft, or Green Hills 103 | CVERSION: Compiler version, e.g. 5.10 104 | OPTIONS: Relevant compiler options, e.g. -O3 105 | NOREG: Dhrystones/second, no register attribute 106 | REG: Dhrystones/second, with register attribute 107 | NOTES: Additional, terse comments on one line 108 | DATE: Date of test, US format MM/DD/YY 109 | SUBMITTER: uucp or domain address (full name) 110 | 111 | 112 | HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ 113 | 114 | Please, if you are using times(2) to measure time, indicate 115 | the HZ value you used in the NOTES field. Something like this is OK: 116 | 117 | NOTES: HZ=100; no inlining... 118 | 119 | HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ HZ 120 | 121 | -- 122 | Rick Richardson, President, PC Research, Inc. 123 | 124 | (201) 542-3734 (voice, nights) OR (201) 389-8963 (voice, days) 125 | uunet!pcrat!rick (UUCP) rick%pcrat.u...@uunet.uu.net (INTERNET) 126 | uunet!pcrat!dry2 (Dhrystone submission forms only) 127 | -------------------------------------------------------------------------------- /v1/pack_1.adb: -------------------------------------------------------------------------------- 1 | 2 | 3 | with Global_Def, Pack_2; 4 | use Global_Def; 5 | 6 | package body Pack_1 is 7 | ------------------- 8 | 9 | Bool_Glob: boolean; 10 | Char_Glob_1, 11 | Char_Glob_2: character; 12 | Array_Glob_1: Array_1_Dim_Integer; 13 | Array_Glob_2: Array_2_Dim_Integer; 14 | Pointer_Glob, 15 | Pointer_Glob_Next: Record_Pointer; 16 | 17 | procedure Proc_4; 18 | procedure Proc_5; 19 | 20 | procedure Proc_0 21 | is 22 | Int_Loc_1, 23 | Int_Loc_2, 24 | Int_Loc_3: One_To_Fifty; 25 | Char_Loc: character; 26 | Enum_Loc: Enumeration; 27 | String_Loc_1, 28 | String_Loc_2: String_30; 29 | begin 30 | 31 | -- Initializations 32 | 33 | Pack_1.Pointer_Glob_Next := new Record_Type; 34 | 35 | Pack_1.Pointer_Glob := new Record_Type 36 | '( 37 | Pointer_Comp => Pack_1.Pointer_Glob_Next, 38 | Discr => Ident_1, 39 | Enum_Comp => Ident_3, 40 | Int_Comp => 40, 41 | String_Comp => "DHRYSTONE PROGRAM, SOME STRING" 42 | ); 43 | 44 | String_Loc_1 := "DHRYSTONE PROGRAM, 1'ST STRING"; 45 | 46 | ----------------- 47 | -- Start timer -- 48 | ----------------- 49 | 50 | Proc_5; 51 | Proc_4; 52 | -- Char_Glob_1 = 'A', Char_Glob_2 = 'B', Bool_Glob = false 53 | Int_Loc_1 := 2; 54 | Int_Loc_2 := 3; 55 | String_Loc_2 := "DHRYSTONE PROGRAM, 2'ND STRING"; 56 | Enum_Loc := Ident_2; 57 | Bool_Glob := not Pack_2.Func_2 (String_Loc_1, String_Loc_2); 58 | -- Bool_Glob = true 59 | while Int_Loc_1 < Int_Loc_2 loop -- loop body executed once 60 | Int_Loc_3 := 5 * Int_Loc_1 - Int_Loc_2; 61 | -- Int_Loc_3 = 7 62 | Pack_2.Proc_7 (Int_Loc_1, Int_Loc_2, Int_Loc_3); 63 | -- Int_Loc_3 = 7 64 | Int_Loc_1 := Int_Loc_1 + 1; 65 | end loop; 66 | -- Int_Loc_1 = 3 67 | Pack_2.Proc_8 (Array_Glob_1, Array_Glob_2, Int_Loc_1, Int_Loc_3); 68 | -- Int_Glob = 5 69 | Proc_1 (Pointer_Glob); 70 | for Char_Index in 'A' .. Char_Glob_2 loop -- loop body executed twice 71 | if Enum_Loc = Pack_2.Func_1 (Char_Index, 'C') 72 | then -- not executed 73 | Pack_2.Proc_6 (Ident_1, Enum_Loc); 74 | end if; 75 | end loop; 76 | -- Enum_Loc = Ident_1 77 | -- Int_Loc_1 = 3, Int_Loc_2 = 3, Int_Loc_3 = 7 78 | Int_Loc_3 := Int_Loc_2 * Int_Loc_1; 79 | Int_Loc_2 := Int_Loc_3 / Int_Loc_1; 80 | Int_Loc_2 := 7 * (Int_Loc_3 - Int_Loc_2) - Int_Loc_1; 81 | Proc_2 (Int_Loc_1); 82 | 83 | ---------------- 84 | -- Stop timer -- 85 | ---------------- 86 | 87 | end Proc_0; 88 | 89 | procedure Proc_1 (Pointer_Par_In: in Record_Pointer) 90 | is -- executed once 91 | Next_Record: Record_Type 92 | renames Pointer_Par_In.Pointer_Comp.all; -- = Pointer_Glob_Next.all 93 | begin 94 | Next_Record := Pointer_Glob.all; 95 | Pointer_Par_In.Int_Comp := 5; 96 | Next_Record.Int_Comp := Pointer_Par_In.Int_Comp; 97 | Next_Record.Pointer_Comp := Pointer_Par_In.Pointer_Comp; 98 | Proc_3 (Next_Record.Pointer_Comp); 99 | -- Next_Record.Pointer_Comp = Pointer_Glob.Pointer_Comp = Pointer_Glob_Next 100 | if Next_Record.Discr = Ident_1 101 | then -- executed 102 | Next_Record.Int_Comp := 6; 103 | Pack_2.Proc_6 (Pointer_Par_In.Enum_Comp, Next_Record.Enum_Comp); 104 | Next_Record.Pointer_Comp := Pointer_Glob.Pointer_Comp; 105 | Pack_2.Proc_7 (Next_Record.Int_Comp, 10, Next_Record.Int_Comp); 106 | else -- not executed 107 | Pointer_Par_In.all := Next_Record; 108 | end if; 109 | end Proc_1; 110 | 111 | procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty) 112 | is -- executed once 113 | -- In_Par_In_Out = 3, becomes 7 114 | Int_Loc: One_To_Fifty; 115 | Enum_Loc: Enumeration; 116 | begin 117 | Int_Loc := Int_Par_In_Out + 10; 118 | loop -- executed once 119 | if Char_Glob_1 = 'A' 120 | then -- executed 121 | Int_Loc := Int_Loc - 1; 122 | Int_Par_In_Out := Int_Loc - Int_Glob; 123 | Enum_Loc := Ident_1; 124 | end if; 125 | exit when Enum_Loc = Ident_1; -- true 126 | end loop; 127 | end Proc_2; 128 | 129 | procedure Proc_3 (Pointer_Par_Out: out Record_Pointer) 130 | is -- executed once 131 | -- Pointer_Par_Out becomes Pointer_Glob 132 | begin 133 | if Pointer_Glob /= null 134 | then -- executed 135 | Pointer_Par_Out := Pointer_Glob.Pointer_Comp; 136 | else -- not executed 137 | Int_Glob := 100; 138 | end if; 139 | Pack_2.Proc_7 (10, Int_Glob, Pointer_Glob.Int_Comp); 140 | end Proc_3; 141 | 142 | procedure Proc_4 -- without parameters 143 | is -- executed once 144 | Bool_Loc: boolean; 145 | begin 146 | Bool_Loc := Char_Glob_1 = 'A'; 147 | Bool_Loc := Bool_Loc or Bool_Glob; 148 | Char_Glob_2 := 'B'; 149 | end Proc_4; 150 | 151 | procedure Proc_5 -- without parameters 152 | is -- executed once 153 | begin 154 | Char_Glob_1 := 'A'; 155 | Bool_Glob := false; 156 | end Proc_5; 157 | 158 | end Pack_1; 159 | -------------------------------------------------------------------------------- /v2.1/d_pack_2.b: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- 8 | -- File: d_pack_2.b (part 5 of 6) 9 | -- 10 | -- Date: August 17, 1988 11 | -- 12 | -- Author: Reinhold P. Weicker 13 | -- 14 | ------------------------------------------------------------------------ 15 | 16 | with Global_Def, Pack_1; 17 | use Global_Def; 18 | 19 | package body Pack_2 is 20 | ------------------- 21 | 22 | function Func_3 (Enum_Par_In: in Enumeration) return boolean; 23 | -- forward declaration 24 | 25 | procedure Proc_6 (Enum_Par_In: in Enumeration; 26 | Enum_Par_Out: out Enumeration) 27 | is -- executed once 28 | -- Enum_Par_In = Ident_3, Enum_Par_Out becomes Ident_2 29 | begin 30 | Enum_Par_Out := Enum_Par_In; 31 | if not Func_3 (Enum_Par_In) 32 | then -- not executed 33 | Enum_Par_Out := Ident_4; 34 | end if; 35 | case Enum_Par_In is 36 | when Ident_1 => Enum_Par_Out := Ident_1; 37 | when Ident_2 => if Pack_1.Int_Glob > 100 38 | then Enum_Par_Out := Ident_1; 39 | else Enum_Par_Out := Ident_4; 40 | end if; 41 | when Ident_3 => Enum_Par_Out := Ident_2; -- executed 42 | when Ident_4 => null; 43 | when Ident_5 => Enum_Par_Out := Ident_3; 44 | end case; 45 | end Proc_6; 46 | 47 | procedure Proc_7 (Int_Par_In_1, 48 | Int_Par_In_2: in One_To_Fifty; 49 | Int_Par_Out: out One_To_Fifty) 50 | is -- executed three times 51 | -- first call: Int_Par_In_1 = 2, Int_Par_In_2 = 3, 52 | -- Int_Par_Out becomes 7 53 | -- second call: Int_Par_In_1 = 6, Int_Par_In_2 = 10, 54 | -- Int_Par_Out becomes 18 55 | -- third call: Int_Par_In_1 = 10, Int_Par_In_2 = 5, 56 | -- Int_Par_Out becomes 17 57 | Int_Loc: One_To_Fifty; 58 | begin 59 | Int_Loc := Int_Par_In_1 + 2; 60 | Int_Par_Out := Int_Par_In_2 + Int_Loc; 61 | end Proc_7; 62 | 63 | procedure Proc_8 (Array_Par_In_Out_1: in out Array_1_Dim_Integer; 64 | Array_Par_In_Out_2: in out Array_2_Dim_Integer; 65 | Int_Par_In_1, 66 | Int_Par_In_2: in integer) 67 | is -- executed once 68 | -- Int_Par_In_1 = 3 69 | -- Int_Par_In_2 = 7 70 | Int_Loc: One_To_Fifty; 71 | begin 72 | Int_Loc := Int_Par_In_1 + 5; 73 | Array_Par_In_Out_1 (Int_Loc) := Int_Par_In_2; 74 | Array_Par_In_Out_1 (Int_Loc+1) := 75 | Array_Par_In_Out_1 (Int_Loc); 76 | Array_Par_In_Out_1 (Int_Loc+30) := Int_Loc; 77 | for Int_Index in Int_Loc .. Int_Loc+1 loop -- loop body executed twice 78 | Array_Par_In_Out_2 (Int_Loc, Int_Index) := Int_Loc; 79 | end loop; 80 | Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) := 81 | Array_Par_In_Out_2 (Int_Loc, Int_Loc-1) + 1; 82 | Array_Par_In_Out_2 (Int_Loc+20, Int_Loc) := 83 | Array_Par_In_Out_1 (Int_Loc); 84 | Pack_1.Int_Glob := 5; 85 | end Proc_8; 86 | 87 | function Func_1 (Char_Par_In_1, 88 | Char_Par_In_2: in Capital_Letter) 89 | return Enumeration 90 | is -- executed three times, returns Ident_1 each time 91 | -- first call: Char_Par_In_1 = 'H', Char_Par_In_2 = 'R' 92 | -- second call: Char_Par_In_1 = 'A', Char_Par_In_2 = 'C' 93 | -- third call: Char_Par_In_1 = 'B', Char_Par_In_2 = 'C' 94 | Char_Loc_1, Char_Loc_2: Capital_Letter; 95 | begin 96 | Char_Loc_1 := Char_Par_In_1; 97 | Char_Loc_2 := Char_Loc_1; 98 | if Char_Loc_2 /= Char_Par_In_2 99 | then -- executed 100 | return Ident_1; 101 | else -- not executed 102 | Pack_1.Char_Glob_1 := Char_Loc_1; 103 | return Ident_2; 104 | end if; 105 | end Func_1; 106 | 107 | function Func_2 (String_Par_In_1, 108 | String_Par_In_2: in String_30) return boolean 109 | is -- executed once, returns false 110 | -- String_Par_In_1 = "DHRYSTONE PROGRAM, 1'ST STRING" 111 | -- String_Par_In_2 = "DHRYSTONE PROGRAM, 2'ND STRING" 112 | Int_Loc: One_To_Thirty; 113 | Char_Loc: Capital_Letter; 114 | begin 115 | Int_Loc := 2; 116 | while Int_Loc <= 2 loop -- loop body executed once 117 | if Func_1 (String_Par_In_1(Int_Loc), 118 | String_Par_In_2(Int_Loc+1)) = Ident_1 119 | then -- executed 120 | Char_Loc := 'A'; 121 | Int_Loc := Int_Loc + 1; 122 | end if; 123 | end loop; 124 | if Char_Loc >= 'W' and Char_Loc < 'Z' 125 | then -- not executed 126 | Int_Loc := 7; 127 | end if; 128 | if Char_Loc = 'R' 129 | then -- not executed 130 | return true; 131 | else -- executed 132 | if String_Par_In_1 = String_Par_In_2 133 | -- if String_Par_In_1 > String_Par_In_2 134 | -- not yet implemented 135 | then -- not executed 136 | Int_Loc := Int_Loc + 7; 137 | Pack_1.Int_Glob := Int_Loc; 138 | return true; 139 | else -- executed 140 | return false; 141 | end if; 142 | end if; 143 | end Func_2; 144 | 145 | function Func_3 (Enum_Par_In: in Enumeration) return boolean 146 | is -- executed once, returns true 147 | -- Enum_Par_In = Ident_3 148 | Enum_Loc: Enumeration; 149 | begin 150 | Enum_Loc := Enum_Par_In; 151 | if Enum_Loc = Ident_3 152 | then -- executed 153 | return true; 154 | else -- not executed 155 | return false; 156 | end if; 157 | end Func_3; 158 | 159 | end Pack_2; 160 | -------------------------------------------------------------------------------- /original-sources/1988-03-08-dhrystone-2.0-1of3: -------------------------------------------------------------------------------- 1 | Path: utzoo!mnetor!uunet!pcrat!dry 2 | From: d...@pcrat.UUCP (Dhrystone) 3 | Newsgroups: comp.arch 4 | Subject: Dhrystone 2.0 (1 of 3) 5 | Message-ID: <492@pcrat.UUCP> 6 | Date: 9 Mar 88 03:16:12 GMT 7 | Organization: PC Research, Inc., Tinton Falls, NJ 8 | Lines: 189 9 | Keywords: benchmark 10 | 11 | 12 | 03/08/88 13 | 14 | As you can see, haste makes waste. Here it is, posted 15 | a second time. There was one bona-fide botch in what 16 | Reinhold sent me. And then I got a hold of it and 17 | tried to convert all the spaces to tabs to conserve 18 | network bandwidth. Big Mistake. So now it's coming 19 | to you in three shar's, with my boiler plate up front. 20 | 21 | Also, as far as the Pascal version possibly failing 22 | a consistency check, we'll have to wait for Reinhold 23 | pass judgement. 24 | 25 | -Rick 26 | #! /bin/sh 27 | # This is a shell archive, meaning: 28 | # 1. Remove everything above the #! /bin/sh line. 29 | # 2. Save the resulting text in a file. 30 | # 3. Execute the file with /bin/sh (not csh) to create: 31 | # README.RER 32 | # Makefile 33 | # submit.frm 34 | # This archive created: Tue Mar 8 21:59:28 1988 35 | export PATH; PATH=/bin:/usr/bin:$PATH 36 | if test -f 'README.RER' 37 | then 38 | echo shar: "will not over-write existing file 'README.RER'" 39 | else 40 | sed 's/^X//' << \SHAR_EOF > 'README.RER' 41 | XSince I was flooded with requests to not wait a day, let alone a week 42 | Xbefore posting Dhrystone 2.0, here it is, without any delay (and no 43 | Xresults, either). 44 | X 45 | XI've enclosed a new submission form (note new address for mailings). 46 | XPlease deluge this mailbox (..!uunet!pcrat!dry2) with your results. 47 | XI'll summarize and repost when the dust clears. Please do not 48 | Xassume that I will pull posted results off of the net (I won't, its 49 | Xtoo much work). 50 | X 51 | XAlso, please make note of the fact that I've attempted to include 52 | Xa Makefile for UNIX. Pay particular attention to the HZ parameter, 53 | Xeven though your power may be 50 or 60 hertz, your computer may not be. 54 | XYou may have to ask someone, read the manual, or check 55 | X /usr/include/sys/param.h 56 | Xfor this information. 57 | X 58 | XThere are two versions to run, one with register variables, and one 59 | Xwithout. Please let the benchmark run for 30,000 loops on sixteen 60 | Xbit machines, and for much longer (a minute or two) on faster machines. 61 | XFor segmented architectures, it is appropriate to submit results for 62 | Xall memory models, as shown below. 63 | X 64 | XHere's a sample submission of results: 65 | X 66 | XDHRYSTONE 2.0 BENCHMARK REPORTING FORM 67 | XMANUF: IBM 68 | XMODEL: PC/AT 69 | XPROC: 80286 70 | XCLOCK: 8 Mhz 71 | XOS: Venix 72 | XOVERSION: SVr2.3 73 | XCOMPILER: AT&T cc 74 | XCVERSION: 11/8/84 75 | XOPTIONS: -O 76 | XNOREG: 1318 77 | XREG: 1450 78 | XNOTES: Small Model 79 | XDATE: 03/04/88 80 | XSUBMITTER: pcrat!rick (Rick Richardson) 81 | XMAILTO: uunet!pcrat!dry2 82 | X 83 | XDHRYSTONE 2.0 BENCHMARK REPORTING FORM 84 | XMANUF: IBM 85 | XMODEL: PC/AT 86 | XPROC: 80286 87 | XCLOCK: 8 Mhz 88 | XOS: Venix 89 | XOVERSION: SVr2.3 90 | XCOMPILER: AT&T cc 91 | XCVERSION: 11/8/84 92 | XOPTIONS: -O -Ml 93 | XNOREG: 1043 94 | XREG: 1043 95 | XNOTES: Large Model 96 | XDATE: 03/04/88 97 | XSUBMITTER: pcrat!rick (Rick Richardson) 98 | XMAILTO: uunet!pcrat!dry2 99 | X 100 | X 101 | X Rick Richardson, President, PC Research, Inc. 102 | X 103 | X(201) 542-3734 (voice, nights) OR (201) 834-1378 (voice, days) 104 | Xuunet!pcrat!rick (UUCP) rick%pcrat.u...@uunet.uu.net (INTERNET) 105 | X uunet!pcrat!dry2 (Dhrystone submission forms only) 106 | SHAR_EOF 107 | fi 108 | if test -f 'Makefile' 109 | then 110 | echo shar: "will not over-write existing file 'Makefile'" 111 | else 112 | sed 's/^X//' << \SHAR_EOF > 'Makefile' 113 | X# 114 | X# Adjust for your system 115 | X# 116 | X# TIME_FUNC, STRUCTASSIGN, and ENUMS selectable by changing order 117 | X# 118 | XCC= cc # C compiler name goes here 119 | X 120 | XTIME_FUNC= -DTIME # Use time(2) for measurement 121 | XTIME_FUNC= -DTIMES # Use times(2) for measurement 122 | XHZ= 60 # Frequency of times(2) clock ticks 123 | X 124 | XSTRUCTASSIGN= -DNOSTRUCTASSIGN # Compiler cannot assign structs 125 | XSTRUCTASSIGN= # Compiler can assign structs 126 | X 127 | XENUMS= -DNOENUMS # Compiler doesn't have enum type 128 | XENUMS= # Compiler does have enum type 129 | X 130 | XOPTIMIZE= -O # Optimization Level 131 | X 132 | XLFLAGS= #Loader Flags 133 | X 134 | XCFLAGS= $(OPTIMIZE) $(TIME_FUNC) -DHZ=$(HZ) $(ENUMS) $(STRUCTASSIGN) $(CFL) 135 | X 136 | X# 137 | X# You shouldn't need to touch the rest 138 | X# 139 | XSRC= dhry_pack_1.c dhry_pack_2.c 140 | XHDR= dhry_global.h 141 | X 142 | Xall: dry2 dry2reg 143 | X 144 | Xdry2: $(SRC) $(HDR) 145 | X $(CC) $(CFLAGS) $(SRC) $(LFLAGS) -o $@ 146 | X 147 | Xdry2reg: $(SRC) $(HDR) 148 | X $(CC) $(CFLAGS) -DREG=register $(SRC) $(LFLAGS) -o $@ 149 | X 150 | Xshar: dry2shar.1 dry2shar.2 dry2shar.3 151 | X 152 | Xdry2shar.1: README.RER Makefile submit.frm 153 | X shar -p X README.RER Makefile submit.frm >$@ 154 | X 155 | Xdry2shar.2: README $(HDR) $(SRC) 156 | X shar -p X README $(HDR) $(SRC) >$@ 157 | X 158 | Xdry2shar.3: dhry.p 159 | X shar -p X dhry.p >$@ 160 | X 161 | Xclean: 162 | X -rm -f *.o 163 | X 164 | Xclobber: clean 165 | X -rm -f dry2 dry2reg dry2shar.* 166 | X 167 | Xpost: 168 | X for i in 1 2 3;\ 169 | X do\ 170 | X cat HEADERS BOILER.$$i dry2shar.$$i |\ 171 | X inews -h -t "Dhrystone 2.0 ($$i of 3)" -n comp.arch;\ 172 | X done 173 | SHAR_EOF 174 | fi 175 | if test -f 'submit.frm' 176 | then 177 | echo shar: "will not over-write existing file 'submit.frm'" 178 | else 179 | sed 's/^X//' << \SHAR_EOF > 'submit.frm' 180 | XDHRYSTONE 2.0 BENCHMARK REPORTING FORM 181 | XMANUF: 182 | XMODEL: 183 | XPROC: 184 | XCLOCK: 185 | XOS: 186 | XOVERSION: 187 | XCOMPILER: 188 | XCVERSION: 189 | XOPTIONS: 190 | XNOREG: 191 | XREG: 192 | XNOTES: 193 | XDATE: 194 | XSUBMITTER: 195 | XMAILTO: uunet!pcrat!dry2 196 | SHAR_EOF 197 | fi 198 | exit 0 199 | # End of shell archive 200 | -------------------------------------------------------------------------------- /v2.0/dhry_pack_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * 4 | * "DHRYSTONE" Benchmark Program 5 | * ----------------------------- 6 | * 7 | * Version: C, Version 2.0 8 | * 9 | * File: dhry_pack_2.c (part 3 of 3) 10 | * 11 | * Date: March 3, 1988 12 | * 13 | * Author: Reinhold P. Weicker 14 | * 15 | **************************************************************************** 16 | */ 17 | 18 | #include "dhry_global.h" 19 | 20 | #ifndef REG 21 | #define REG 22 | /* REG becomes defined as empty */ 23 | /* i.e. no register variables */ 24 | #endif 25 | 26 | extern int Int_Glob; 27 | extern char Ch_1_Glob; 28 | 29 | 30 | Proc_6 (Enum_Val_Par, Enum_Ref_Par) 31 | /*********************************/ 32 | /* executed once */ 33 | /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ 34 | 35 | Enumeration Enum_Val_Par; 36 | Enumeration *Enum_Ref_Par; 37 | { 38 | *Enum_Ref_Par = Enum_Val_Par; 39 | if (! Func_3 (Enum_Val_Par)) 40 | /* then, not executed */ 41 | *Enum_Ref_Par = Ident_4; 42 | switch (Enum_Val_Par) 43 | { 44 | case Ident_1: 45 | *Enum_Ref_Par = Ident_1; 46 | break; 47 | case Ident_2: 48 | if (Int_Glob > 100) 49 | /* then */ 50 | *Enum_Ref_Par = Ident_1; 51 | else *Enum_Ref_Par = Ident_4; 52 | break; 53 | case Ident_3: /* executed */ 54 | *Enum_Ref_Par = Ident_2; 55 | break; 56 | case Ident_4: break; 57 | case Ident_5: 58 | *Enum_Ref_Par = Ident_3; 59 | break; 60 | } /* switch */ 61 | } /* Proc_6 */ 62 | 63 | 64 | Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) 65 | /**********************************************/ 66 | /* executed three times */ 67 | /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ 68 | /* Int_Par_Ref becomes 7 */ 69 | /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ 70 | /* Int_Par_Ref becomes 17 */ 71 | /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ 72 | /* Int_Par_Ref becomes 18 */ 73 | One_Fifty Int_1_Par_Val; 74 | One_Fifty Int_2_Par_Val; 75 | One_Fifty *Int_Par_Ref; 76 | { 77 | One_Fifty Int_Loc; 78 | 79 | Int_Loc = Int_1_Par_Val + 2; 80 | *Int_Par_Ref = Int_2_Par_Val + Int_Loc; 81 | } /* Proc_7 */ 82 | 83 | 84 | Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) 85 | /*********************************************************************/ 86 | /* executed once */ 87 | /* Int_Par_Val_1 == 3 */ 88 | /* Int_Par_Val_2 == 7 */ 89 | Arr_1_Dim Arr_1_Par_Ref; 90 | Arr_2_Dim Arr_2_Par_Ref; 91 | int Int_1_Par_Val; 92 | int Int_2_Par_Val; 93 | { 94 | REG One_Fifty Int_Index; 95 | REG One_Fifty Int_Loc; 96 | 97 | Int_Loc = Int_1_Par_Val + 5; 98 | Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; 99 | Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; 100 | Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; 101 | for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) 102 | Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; 103 | Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; 104 | Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; 105 | Int_Glob = 5; 106 | } /* Proc_8 */ 107 | 108 | 109 | Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) 110 | /*************************************************/ 111 | /* executed three times */ 112 | /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ 113 | /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ 114 | /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ 115 | 116 | Capital_Letter Ch_1_Par_Val; 117 | Capital_Letter Ch_2_Par_Val; 118 | { 119 | Capital_Letter Ch_1_Loc; 120 | Capital_Letter Ch_2_Loc; 121 | 122 | Ch_1_Loc = Ch_1_Par_Val; 123 | Ch_2_Loc = Ch_1_Loc; 124 | if (Ch_2_Loc != Ch_2_Par_Val) 125 | /* then, executed */ 126 | return (Ident_1); 127 | else /* not executed */ 128 | { 129 | Ch_1_Glob = Ch_1_Loc; 130 | return (Ident_2); 131 | } 132 | } /* Func_1 */ 133 | 134 | 135 | Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) 136 | /*************************************************/ 137 | /* executed once */ 138 | /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ 139 | /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ 140 | 141 | Str_30 Str_1_Par_Ref; 142 | Str_30 Str_2_Par_Ref; 143 | { 144 | REG One_Thirty Int_Loc; 145 | Capital_Letter Ch_Loc; 146 | 147 | Int_Loc = 2; 148 | while (Int_Loc <= 2) /* loop body executed once */ 149 | if (Func_1 (Str_1_Par_Ref[Int_Loc], 150 | Str_2_Par_Ref[Int_Loc+1]) == Ident_1) 151 | /* then, executed */ 152 | { 153 | Ch_Loc = 'A'; 154 | Int_Loc += 1; 155 | } /* if, while */ 156 | if (Ch_Loc >= 'W' && Ch_Loc < 'Z') 157 | /* then, not executed */ 158 | Int_Loc = 7; 159 | if (Ch_Loc == 'R') 160 | /* then, not executed */ 161 | return (true); 162 | else /* executed */ 163 | { 164 | if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) 165 | /* then, not executed */ 166 | { 167 | Int_Loc += 7; 168 | Int_Glob = Int_Loc; 169 | return (true); 170 | } 171 | else /* executed */ 172 | return (false); 173 | } /* if Ch_Loc */ 174 | } /* Func_2 */ 175 | 176 | 177 | Boolean Func_3 (Enum_Par_Val) 178 | /***************************/ 179 | /* executed once */ 180 | /* Enum_Par_Val == Ident_3 */ 181 | Enumeration Enum_Par_Val; 182 | { 183 | Enumeration Enum_Loc; 184 | 185 | Enum_Loc = Enum_Par_Val; 186 | if (Enum_Loc == Ident_3) 187 | /* then, executed */ 188 | return (true); 189 | } /* Func_3 */ 190 | 191 | -------------------------------------------------------------------------------- /v2.1/dhry_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * 4 | * "DHRYSTONE" Benchmark Program 5 | * ----------------------------- 6 | * 7 | * Version: C, Version 2.1 8 | * 9 | * File: dhry_2.c (part 3 of 3) 10 | * 11 | * Date: May 25, 1988 12 | * 13 | * Author: Reinhold P. Weicker 14 | * 15 | **************************************************************************** 16 | */ 17 | 18 | #include "dhry.h" 19 | 20 | #ifndef REG 21 | #define REG 22 | /* REG becomes defined as empty */ 23 | /* i.e. no register variables */ 24 | #endif 25 | 26 | extern int Int_Glob; 27 | extern char Ch_1_Glob; 28 | 29 | 30 | Proc_6 (Enum_Val_Par, Enum_Ref_Par) 31 | /*********************************/ 32 | /* executed once */ 33 | /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */ 34 | 35 | Enumeration Enum_Val_Par; 36 | Enumeration *Enum_Ref_Par; 37 | { 38 | *Enum_Ref_Par = Enum_Val_Par; 39 | if (! Func_3 (Enum_Val_Par)) 40 | /* then, not executed */ 41 | *Enum_Ref_Par = Ident_4; 42 | switch (Enum_Val_Par) 43 | { 44 | case Ident_1: 45 | *Enum_Ref_Par = Ident_1; 46 | break; 47 | case Ident_2: 48 | if (Int_Glob > 100) 49 | /* then */ 50 | *Enum_Ref_Par = Ident_1; 51 | else *Enum_Ref_Par = Ident_4; 52 | break; 53 | case Ident_3: /* executed */ 54 | *Enum_Ref_Par = Ident_2; 55 | break; 56 | case Ident_4: break; 57 | case Ident_5: 58 | *Enum_Ref_Par = Ident_3; 59 | break; 60 | } /* switch */ 61 | } /* Proc_6 */ 62 | 63 | 64 | Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref) 65 | /**********************************************/ 66 | /* executed three times */ 67 | /* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */ 68 | /* Int_Par_Ref becomes 7 */ 69 | /* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */ 70 | /* Int_Par_Ref becomes 17 */ 71 | /* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */ 72 | /* Int_Par_Ref becomes 18 */ 73 | One_Fifty Int_1_Par_Val; 74 | One_Fifty Int_2_Par_Val; 75 | One_Fifty *Int_Par_Ref; 76 | { 77 | One_Fifty Int_Loc; 78 | 79 | Int_Loc = Int_1_Par_Val + 2; 80 | *Int_Par_Ref = Int_2_Par_Val + Int_Loc; 81 | } /* Proc_7 */ 82 | 83 | 84 | Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val) 85 | /*********************************************************************/ 86 | /* executed once */ 87 | /* Int_Par_Val_1 == 3 */ 88 | /* Int_Par_Val_2 == 7 */ 89 | Arr_1_Dim Arr_1_Par_Ref; 90 | Arr_2_Dim Arr_2_Par_Ref; 91 | int Int_1_Par_Val; 92 | int Int_2_Par_Val; 93 | { 94 | REG One_Fifty Int_Index; 95 | REG One_Fifty Int_Loc; 96 | 97 | Int_Loc = Int_1_Par_Val + 5; 98 | Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val; 99 | Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc]; 100 | Arr_1_Par_Ref [Int_Loc+30] = Int_Loc; 101 | for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index) 102 | Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc; 103 | Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1; 104 | Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc]; 105 | Int_Glob = 5; 106 | } /* Proc_8 */ 107 | 108 | 109 | Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val) 110 | /*************************************************/ 111 | /* executed three times */ 112 | /* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */ 113 | /* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */ 114 | /* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */ 115 | 116 | Capital_Letter Ch_1_Par_Val; 117 | Capital_Letter Ch_2_Par_Val; 118 | { 119 | Capital_Letter Ch_1_Loc; 120 | Capital_Letter Ch_2_Loc; 121 | 122 | Ch_1_Loc = Ch_1_Par_Val; 123 | Ch_2_Loc = Ch_1_Loc; 124 | if (Ch_2_Loc != Ch_2_Par_Val) 125 | /* then, executed */ 126 | return (Ident_1); 127 | else /* not executed */ 128 | { 129 | Ch_1_Glob = Ch_1_Loc; 130 | return (Ident_2); 131 | } 132 | } /* Func_1 */ 133 | 134 | 135 | Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref) 136 | /*************************************************/ 137 | /* executed once */ 138 | /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */ 139 | /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */ 140 | 141 | Str_30 Str_1_Par_Ref; 142 | Str_30 Str_2_Par_Ref; 143 | { 144 | REG One_Thirty Int_Loc; 145 | Capital_Letter Ch_Loc; 146 | 147 | Int_Loc = 2; 148 | while (Int_Loc <= 2) /* loop body executed once */ 149 | if (Func_1 (Str_1_Par_Ref[Int_Loc], 150 | Str_2_Par_Ref[Int_Loc+1]) == Ident_1) 151 | /* then, executed */ 152 | { 153 | Ch_Loc = 'A'; 154 | Int_Loc += 1; 155 | } /* if, while */ 156 | if (Ch_Loc >= 'W' && Ch_Loc < 'Z') 157 | /* then, not executed */ 158 | Int_Loc = 7; 159 | if (Ch_Loc == 'R') 160 | /* then, not executed */ 161 | return (true); 162 | else /* executed */ 163 | { 164 | if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0) 165 | /* then, not executed */ 166 | { 167 | Int_Loc += 7; 168 | Int_Glob = Int_Loc; 169 | return (true); 170 | } 171 | else /* executed */ 172 | return (false); 173 | } /* if Ch_Loc */ 174 | } /* Func_2 */ 175 | 176 | 177 | Boolean Func_3 (Enum_Par_Val) 178 | /***************************/ 179 | /* executed once */ 180 | /* Enum_Par_Val == Ident_3 */ 181 | Enumeration Enum_Par_Val; 182 | { 183 | Enumeration Enum_Loc; 184 | 185 | Enum_Loc = Enum_Par_Val; 186 | if (Enum_Loc == Ident_3) 187 | /* then, executed */ 188 | return (true); 189 | else /* not executed */ 190 | return (false); 191 | } /* Func_3 */ 192 | 193 | -------------------------------------------------------------------------------- /v2.1/d_pack_1.b: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- (Portable Version) 8 | -- 9 | -- File: d_pack_1.b (part 4 of 6) 10 | -- 11 | -- Date: December 17, 1988 12 | -- 13 | -- Author: Reinhold P. Weicker 14 | -- 15 | -- Comments: This package contains, along with other procedures, 16 | -- Proc_0 which encloses the measurement loop 17 | -- and the statements printing the results. 18 | -- 19 | -- For execution time measurement, a call to the procedure 20 | -- "Clock" of package CALENDAR is used. 21 | -- Note that Clock returns the elapsed time 22 | -- (wall clock time). When more processes than Dhrystone 23 | -- are running, the time values returned by the procedures 24 | -- of CALENDAR do NOT represent the (process-specific) 25 | -- execution time of Dhrystone. 26 | -- 27 | -- For more accurate time measurement, replace the calls to 28 | -- Clock by calls to (implementation-specific) 29 | -- procedures that return the process-specific time. 30 | -- However, no such procedures are defined in Standard Ada. 31 | -- 32 | -- Timing issues for Ada are discussed in "Toward Real-Time 33 | -- Performance Benchmarks for Ada" (Russell M. Clapp et al., 34 | -- CACM vol. 29, no. 8, August 1986, pp. 760-778). 35 | -- 36 | ------------------------------------------------------------------------ 37 | 38 | with Global_Def, Pack_2, TEXT_IO, CALENDAR; 39 | pragma ELABORATE (TEXT_IO); 40 | use Global_Def, TEXT_IO; 41 | 42 | package body Pack_1 is 43 | ------------------- 44 | 45 | package INT_IO is new TEXT_IO.INTEGER_IO (Integer); 46 | package FLOAT_IO is new TEXT_IO.FLOAT_IO (Float); 47 | package ENUM_IO is new TEXT_IO.ENUMERATION_IO (Enumeration); 48 | package BOOL_IO is new TEXT_IO.ENUMERATION_IO (Boolean); 49 | use INT_IO, FLOAT_IO, ENUM_IO, BOOL_IO; 50 | 51 | 52 | Bool_Glob: boolean; 53 | Char_Glob_2: character; 54 | Array_Glob_1: Array_1_Dim_Integer; 55 | Array_Glob_2: Array_2_Dim_Integer; 56 | Pointer_Glob, 57 | Pointer_Glob_Next: Record_Pointer; 58 | 59 | procedure Proc_4; 60 | procedure Proc_5; 61 | 62 | -- for measurement: 63 | Too_Small_Time: constant := 2.0; 64 | -- Measurements should last at least 2 seconds 65 | Max_Number_Of_Runs: constant := 1_000_000; 66 | subtype Run_Range is integer range 1 .. Max_Number_Of_Runs; 67 | 68 | procedure Proc_0 69 | is 70 | Int_Loc_1, 71 | Int_Loc_2, 72 | Int_Loc_3: One_To_Fifty; 73 | Char_Loc: character; 74 | Enum_Loc: Enumeration; 75 | String_Loc_1, 76 | String_Loc_2: String_30; 77 | 78 | -- Variables for time measurement: 79 | Run_Index, 80 | Number_Of_Runs: Run_Range; 81 | Begin_Time, 82 | End_Time: Calendar.Time; 83 | Run_Time: Duration; 84 | Microseconds, 85 | Dhry_Per_Sec: float; 86 | 87 | begin 88 | 89 | -- Initializations 90 | 91 | Pack_1.Pointer_Glob_Next := new Record_Type; 92 | 93 | Pack_1.Pointer_Glob := new Record_Type 94 | '( 95 | Pointer_Comp => Pack_1.Pointer_Glob_Next, 96 | Discr => Ident_1, 97 | Enum_Comp => Ident_3, 98 | Int_Comp => 40, 99 | String_Comp => "DHRYSTONE PROGRAM, SOME STRING" 100 | ); 101 | 102 | String_Loc_1 := "DHRYSTONE PROGRAM, 1'ST STRING"; 103 | 104 | Array_Glob_2 (8,7) := 10; 105 | 106 | Put_Line ("Dhrystone Benchmark, Version 2.1 (Language: Ada)"); 107 | New_Line; 108 | Put_Line ("Please give the number of runs through the benchmark: "); 109 | Put ("> "); 110 | Get (Number_Of_Runs); 111 | 112 | Put ("Execution starts, "); 113 | Put (Number_Of_Runs); 114 | Put (" runs through Dhrystone"); 115 | New_Line; 116 | 117 | ----------------- 118 | -- Start timer -- 119 | ----------------- 120 | 121 | Begin_Time := Calendar.Clock; 122 | 123 | for Run_Index in 1 .. Number_Of_Runs Loop 124 | 125 | Proc_5; 126 | Proc_4; 127 | -- Char_Glob_ 'A', Char_Glob_2 = 'B', Bool_Glob = false 128 | Int_Loc_1 := 2; 129 | Int_Loc_2 := 3; 130 | String_Loc_2 := "DHRYSTONE PROGRAM, 2'ND STRING"; 131 | Enum_Loc := Ident_2; 132 | Bool_Glob := not Pack_2.Func_2 (String_Loc_1, String_Loc_2); 133 | -- Bool_Glob = true 134 | while Int_Loc_1 < Int_Loc_2 loop -- loop body executed once 135 | Int_Loc_3 := 5 * Int_Loc_1 - Int_Loc_2; 136 | -- Int_Loc_3 = 7 137 | Pack_2.Proc_7 (Int_Loc_1, Int_Loc_2, Int_Loc_3); 138 | -- Int_Loc_3 = 7 139 | Int_Loc_1 := Int_Loc_1 + 1; 140 | end loop; 141 | -- Int_Loc_1 = 3 142 | Pack_2.Proc_8 (Array_Glob_1, Array_Glob_2, Int_Loc_1, Int_Loc_3); 143 | -- Int_Glob = 5 144 | Proc_1 (Pointer_Glob); 145 | for Char_Index in 'A' .. Char_Glob_2 loop -- loop body executed twice 146 | if Enum_Loc = Pack_2.Func_1 (Char_Index, 'C') 147 | then -- not executed 148 | Pack_2.Proc_6 (Ident_1, Enum_Loc); 149 | String_Loc_2 := "DHRYSTONE PROGRAM, 3'RD STRING"; 150 | Int_Loc_2 := Run_Index; 151 | Int_Glob := Run_Index; 152 | end if; 153 | end loop; 154 | -- Enum_Loc = Ident_1 155 | -- Int_Loc_1 = 3, Int_Loc_2 = 3, Int_Loc_3 = 7 156 | Int_Loc_2 := Int_Loc_2 * Int_Loc_1; 157 | Int_Loc_1 := Int_Loc_2 / Int_Loc_3; 158 | Int_Loc_2 := 7 * (Int_Loc_2 - Int_Loc_3) - Int_Loc_1; 159 | -- Int_Loc_1 = 1, Int_Loc_2 = 13, Int_Loc_3 = 7 160 | Proc_2 (Int_Loc_1); 161 | -- Int_Loc_1 = 5 162 | 163 | end loop; -- for Run_Index 164 | 165 | ---------------- 166 | -- Stop timer -- 167 | ---------------- 168 | 169 | End_Time := Calendar.Clock; 170 | 171 | Put_Line ("Execution ends"); 172 | New_Line; 173 | Put_Line ("Final values of the variables used in the benchmark:"); 174 | New_Line; 175 | 176 | INT_IO.DEFAULT_WIDTH := 6; 177 | Put ("Int_Glob: "); 178 | Put (Int_Glob); 179 | New_Line; 180 | Put_Line (" should be: 5"); 181 | Put ("Bool_Glob: "); 182 | Put (Bool_Glob); 183 | New_Line; 184 | Put_Line (" should be: TRUE"); 185 | Put ("Char_Glob_1: "); 186 | Put (Char_Glob_1); 187 | New_Line; 188 | Put_Line (" should be: A"); 189 | Put ("Char_Glob_2: "); 190 | Put (Char_Glob_2); 191 | New_Line; 192 | Put_Line (" should be: B"); 193 | Put ("Array_Glob_1 (8): "); 194 | Put (Array_Glob_1 (8)); 195 | New_Line; 196 | Put_Line (" should be: 7"); 197 | Put ("Array_Glob_2 (8,7): "); 198 | Put (Array_Glob_2 (8,7)); 199 | New_Line; 200 | Put_Line (" should be: Number_Of_Runs + 10"); 201 | Put_Line ("Pointer_Glob."); 202 | Put_Line (" Pointer_Comp: (implementation-dependent)"); 203 | Put (" Discr: "); 204 | Put (Pointer_Glob.Discr); 205 | New_Line; 206 | Put_Line (" should be: IDENT_1"); 207 | Put (" Enum_Comp: "); 208 | Put (Pointer_Glob.Enum_Comp); 209 | New_Line; 210 | Put_Line (" should be: IDENT_3"); 211 | Put (" Int_Comp: "); 212 | Put (Pointer_Glob.Int_Comp); 213 | New_Line; 214 | Put_Line (" should be: 17"); 215 | Put (" String_Comp: "); 216 | for I in 1 .. 30 loop 217 | Put (Pointer_Glob.String_Comp (I)); 218 | end loop; 219 | New_Line; 220 | Put_Line (" should be: DHRYSTONE PROGRAM, SOME STRING"); 221 | Put_Line ("Pointer_Glob_Next."); 222 | Put_Line (" Pointer_Comp: (implementation-dependent)"); 223 | Put (" Discr: "); 224 | Put (Pointer_Glob_Next.Discr); 225 | New_Line; 226 | Put_Line (" should be: IDENT_1"); 227 | Put (" Enum_Comp: "); 228 | Put (Pointer_Glob_Next.Enum_Comp); 229 | New_Line; 230 | Put_Line (" should be: IDENT_2"); 231 | Put (" Int_Comp: "); 232 | Put (Pointer_Glob_Next.Int_Comp); 233 | New_Line; 234 | Put_Line (" should be: 18"); 235 | Put (" String_Comp: "); 236 | for I in 1 .. 30 loop 237 | Put (Pointer_Glob_Next.String_Comp (I)); 238 | end loop; 239 | New_Line; 240 | Put_Line (" should be: DHRYSTONE PROGRAM, SOME STRING"); 241 | Put ("Int_Loc_1: "); 242 | Put (Int_Loc_1); 243 | New_Line; 244 | Put_Line (" should be: 5"); 245 | Put ("Int_Loc_2: "); 246 | Put (Int_Loc_2); 247 | New_Line; 248 | Put_Line (" should be: 13"); 249 | Put ("Int_Loc_3: "); 250 | Put (Int_Loc_3); 251 | New_Line; 252 | Put_Line (" should be: 7"); 253 | Put ("Enum_Loc: "); 254 | Put (Enum_Loc); 255 | New_Line; 256 | Put_Line (" should be: IDENT_2"); 257 | Put ("String_Loc_1 "); 258 | for I in 1 .. 30 loop 259 | Put (String_Loc_1 (I)); 260 | end loop; 261 | New_Line; 262 | Put_Line (" should be: DHRYSTONE PROGRAM, 1'ST STRING"); 263 | Put ("String_Loc_2 "); 264 | for I in 1 .. 30 loop 265 | Put (String_Loc_2 (I)); 266 | end loop; 267 | New_Line; 268 | Put_Line (" should be: DHRYSTONE PROGRAM, 2'ND STRING"); 269 | New_Line; 270 | 271 | -- Compute Execution Time 272 | 273 | Run_Time := Calendar."-" (End_Time, Begin_Time); 274 | if Run_Time < Too_Small_Time 275 | then 276 | Put_Line ("Measured Time too small to obtain meaningful results"); 277 | Put_Line ("Please increase number of runs"); 278 | else 279 | Microseconds := 1_000_000.0 * float (Run_Time) / float (Number_Of_Runs); 280 | Dhry_Per_Sec := float (Number_of_Runs) / float (Run_Time); 281 | Put ("Microseconds for one run through Dhrystone: "); 282 | Put (Microseconds, Aft => 2, Exp => 0); 283 | New_Line; 284 | Put ("Dhrystones per second: "); 285 | Put (Dhry_Per_Sec, Aft => 2, Exp => 0); 286 | New_Line; 287 | end if; 288 | New_Line; 289 | 290 | end Proc_0; 291 | 292 | procedure Proc_1 (Pointer_Par_In: in Record_Pointer) 293 | is -- executed once 294 | Next_Record: Record_Type 295 | renames Pointer_Par_In.Pointer_Comp.all; -- = Pointer_Glob_Next.all 296 | begin 297 | Next_Record := Pointer_Glob.all; 298 | Pointer_Par_In.Int_Comp := 5; 299 | Next_Record.Int_Comp := Pointer_Par_In.Int_Comp; 300 | Next_Record.Pointer_Comp := Pointer_Par_In.Pointer_Comp; 301 | Proc_3 (Next_Record.Pointer_Comp); 302 | -- Next_Record.Pointer_Comp = Pointer_Glob.Pointer_Comp = Pointer_Glob_Next 303 | if Next_Record.Discr = Ident_1 304 | then -- executed 305 | Next_Record.Int_Comp := 6; 306 | Pack_2.Proc_6 (Pointer_Par_In.Enum_Comp, Next_Record.Enum_Comp); 307 | Next_Record.Pointer_Comp := Pointer_Glob.Pointer_Comp; 308 | Pack_2.Proc_7 (Next_Record.Int_Comp, 10, Next_Record.Int_Comp); 309 | else -- not executed 310 | Pointer_Par_In.all := Next_Record; 311 | end if; 312 | end Proc_1; 313 | 314 | procedure Proc_2 (Int_Par_In_Out: in out One_To_Fifty) 315 | is -- executed once 316 | -- In_Par_In_Out = 3, becomes 7 317 | Int_Loc: One_To_Fifty; 318 | Enum_Loc: Enumeration; 319 | begin 320 | Int_Loc := Int_Par_In_Out + 10; 321 | loop -- executed once 322 | if Char_Glob_1 = 'A' 323 | then -- executed 324 | Int_Loc := Int_Loc - 1; 325 | Int_Par_In_Out := Int_Loc - Int_Glob; 326 | Enum_Loc := Ident_1; 327 | end if; 328 | exit when Enum_Loc = Ident_1; -- true 329 | end loop; 330 | end Proc_2; 331 | 332 | procedure Proc_3 (Pointer_Par_Out: out Record_Pointer) 333 | is -- executed once 334 | -- Pointer_Par_Out becomes Pointer_Glob 335 | begin 336 | if Pointer_Glob /= null 337 | then -- executed 338 | Pointer_Par_Out := Pointer_Glob.Pointer_Comp; 339 | end if; 340 | Pack_2.Proc_7 (10, Int_Glob, Pointer_Glob.Int_Comp); 341 | end Proc_3; 342 | 343 | procedure Proc_4 -- without parameters 344 | is -- executed once 345 | Bool_Loc: boolean; 346 | begin 347 | Bool_Loc := Char_Glob_1 = 'A'; 348 | Bool_Glob := Bool_Loc or Bool_Glob; 349 | Char_Glob_2 := 'B'; 350 | end Proc_4; 351 | 352 | procedure Proc_5 -- without parameters 353 | is -- executed once 354 | begin 355 | Char_Glob_1 := 'A'; 356 | Bool_Glob := false; 357 | end Proc_5; 358 | 359 | end Pack_1; 360 | 361 | 362 | -------------------------------------------------------------------------------- /v1/user-guide.txt: -------------------------------------------------------------------------------- 1 | MEASUREMENTS WITH THE "DHRYSTONE" BENCHMARK PROGRAM 2 | - USER'S GUIDE - 3 | 4 | REINHOLD P. WEICKER 5 | 6 | OCTOBER 1984 7 | 8 | 9 | 10 | 1. Introduction 11 | 12 | 13 | For "Communication of the ACM", I wrote a paper "Dhrystone: A Synthetic 14 | Systems Programming Benchmark" which appeared in the October issue of 15 | the journal (vol. 27, no. 10, Oct. 1984, p. 1013-1030). The paper 16 | consists of two main parts: First, statistical data about the use of 17 | programming language features (especially in the area of systems 18 | programming) are summarized, and second, a synthetic benchmark program, 19 | written in Ada, is given that is based on these data. 20 | 21 | I am posting the program here in Usenet for those who are interested in 22 | using the "Dhrystone" benchmark program for measurements. The 23 | distribution consists of four parts: 24 | 25 | - Part 1 is this paper (user's guide) containing hints that 26 | should be taken into account when the program is used for 27 | benchmarking, 28 | 29 | - Part 2 is the program (reference version) in Ada, 30 | 31 | - Part 3 is the program (measurement version) in Pascal, 32 | 33 | - Part 4 is the program (measurement version) in C. 34 | 35 | A "reference" version contains just the program text, together with 36 | comments on the statistics, a "measurement" version is a versions where 37 | statements for execution time measurement have been inserted. See 38 | section 4 for more details on measurement methods. 39 | 40 | In the case of Ada, the "reference" versions contains the program text 41 | as published. In the cases of Pascal and C, reference versions (not 42 | distributed here) contain an equivalent program text in these languages. 43 | See the publication for remarks on language issues that have to be 44 | considered when the program is translated to languages other than Ada. 45 | 46 | In the "measurement" versions, some statements (those accessing the 47 | operating system clock) are implementation-dependent. The sample 48 | measurement version given here can be used on Berkeley UNIX systems (4.2 49 | bsd). Of course, for measurements on other systems these statements 50 | have to be changed according to the language library routines available 51 | on these systems. 52 | 53 | The program versions distributed via Usenet contain the program in one 54 | file per programming language, I didn't want to flood the net with too 55 | many versions or with too many small units. However, the understanding 56 | is that the program (Ada and C versions) consists of several modules 57 | (compilation units) that can be compiled separately; see section 3 for a 58 | discussion of compilation and linkage issues (program in one file vs. 59 | program in several files). Versions with the source program in several 60 | files can be obtained easily by "cutting" the program into parts at the 61 | obvious locations. In the case of C, suitable "#include" statements and 62 | an "extern" declaration need to be added. 63 | 64 | Similarly, the reference versions for Pascal and C can be obtained from 65 | the files sent via Usenet by removing the statements for measurement, 66 | the I/O statements and the loops around the main procedure. 67 | 68 | 69 | 70 | 2. Errors / Inconsistencies 71 | 72 | 73 | There are two minor inconsistencies in the published version of the 74 | program which were detected too late for a correction in the published 75 | version: 76 | 77 | - In the comment at the beginning of the function body for 78 | Func_2, the beginning of the string literal should read 79 | "DHRYSTONE PROGRAM, ..." instead of "DHRYSTONE, ..." for both 80 | String_Par_In_1 and String_Par_In_2. 81 | 82 | The code is correct, just the comment text is incorrect; the 83 | two strings are different in the 20th, not in the 12th 84 | character. 85 | 86 | - It can be argued that the first "if" statement in Func_2 87 | should have been formulated 88 | 89 | if Char_Loc >= 'W' and then Char_Loc < 'Z' 90 | 91 | rather than 92 | 93 | if Char_Loc >= 'W' and Char_Loc < 'Z' 94 | 95 | since a programmer writing such a program would only be 96 | interested in the value of the "if" condition as a whole, 97 | there is no need to evaluate "Char_Loc < 'Z'" if "Char_Loc >= 98 | 'W'" evaluates to "false" (however, it doesn't hurt either). 99 | 100 | In the C version of the program, I used for this statement the 101 | operator "&&" (and-then) rather than "&" since in C, different 102 | from Ada and Pascal, "&" forces the compiler to interpret the 103 | result as integer (there is no data type boolean in C) and to 104 | apply a bitwise "and" operation. However, I left the Ada 105 | version as published since I didn't want to change the program 106 | after publication, even if there is now a slight inconsistency 107 | between the Ada and the C version. 108 | 109 | 110 | 111 | 3. Compilation and Linkage Issues 112 | 113 | 114 | 3.1. Ada Version 115 | 116 | The "Dhrystone" program in its original (Ada) version consists of six 117 | library units in the sense of Ada: Two packages (Pack_1 and Pack_2) 118 | consisting of both specification and body, one package (Global_Def) with 119 | specification only, and one subprogram (Main). The package structure is 120 | intended since this is the natural way for programming in Ada. 121 | 122 | As far as benchmarking and execution times are concerned, there can be 123 | systems where calls and data accesses across package boundaries have 124 | execution times different from those within a package. In addition, the 125 | execution time may depend upon the way the program is compiled and 126 | executed; there are two possible ways: 127 | 128 | 129 | 1. the six units are compiled separately and linked together 130 | later, 131 | 132 | 2. the six units are submitted to the compiler in one source 133 | file. 134 | 135 | 136 | For many Ada systems there will be no difference in execution time, as 137 | far as the two compilation models are concerned. However, for some 138 | machines there may be a difference since different representations may 139 | be used for addresses (e.g., 16 bit or 32 bit), depending on the 140 | compilation and linkage model used. 141 | 142 | If there is a difference in execution time, the times for both models 143 | should be measured; model (1) is the one that corresponds more to actual 144 | software development. Ada was explicitly designed for large software 145 | projects that use separate compilation. 146 | 147 | 148 | 3.2. C Version 149 | 150 | C does not have a package structure similar to Ada, but it has features 151 | for independent compilation. Therefore, the same consideration apply as 152 | described above for Ada. 153 | 154 | The program structure of the C version is assumed to be similar to the 155 | Ada version, with the difference that there is no separation between 156 | specification and body, and that "main" and "Proc_0" can be the same 157 | procedure. There are three modules, where module 1 contains constant 158 | definitions and type declarations only, and the two other modules 159 | contain the executable routines of the program: 160 | 161 | 162 | - Module 2 contains the global variables and procedures main, 163 | Proc_1, ..., Proc_5. 164 | 165 | - Module 3 contains procedures Proc_6, ..., Proc_8, and 166 | functions Func_1, ... Func_3. 167 | 168 | 169 | If they are compiled separately, these modules use an "#include" to 170 | refer to the module with the global definitions. 171 | 172 | 173 | 3.3. Pascal Version 174 | 175 | Although many Pascal systems provide features for independent 176 | compilation, this is not part of the ISO or ANSI language standard. 177 | Therefore it is not possible to formulate a portable Pascal version with 178 | several modules, and this set contains only a version with the program 179 | in one source file. 180 | 181 | 182 | 4. Measurement 183 | 184 | 185 | 4.1. Method of Measurement 186 | 187 | For measuring the execution time, I have prepared (Pascal and C) 188 | versions of the program which use the normal method: The program text 189 | between the comments "Start timer" and "Stop timer" is enclosed in a 190 | loop, and the loop is executed often enough that the time can be 191 | measured. (Problems with respect to a cache have been discussed in the 192 | publication.) To get an exact result, the execution time of the same 193 | number of empty loops is subtracted. 194 | 195 | On a single-user system, the output statements inserted in the 196 | measurement versions can be used to measure the elapsed time manually 197 | with a stopwatch. On a multi-user system, this obviously does not give 198 | the expected result unless it is guaranteed that no other process is 199 | running on the system. Fortunately, most programming language 200 | implementations provide a call to a runtime library function with the 201 | name "clock", "runtime", or similar that returns the process-specific 202 | clock, measured in some time unit. 203 | 204 | I used the subroutines "clock" (Pascal) and "times" (C) for measurements 205 | on a VAX 11/780 running Berkeley UNIX (4.2 bsd). It seems that a 206 | certain degree of inaccuracy cannot be avoided due to inaccuracies in 207 | the operating system clock, influences of time slicing, different 208 | mappings of pages to physical memory, etc. As an example, Berkely UNIX 209 | gives for C the value of the clock in two parts, "user time" and "system 210 | time". Although the program does not execute any explicit operating 211 | system calls between the measurement points, the system time is not 0 212 | (it usually lies between 2 and 5 % of the user time). For Pascal, only 213 | a time called "user time" is available. 214 | 215 | 216 | 4.2. Control of Results 217 | 218 | When the program is entered into the computer manually, care should be 219 | taken that no typing errors occur; there is no straightforward 220 | indication that the program executes exactly the statements it is 221 | supposed to execute. I didn't see a reasonable way to have the program 222 | compute result values that can be checked easily, while at the same time 223 | maintaining the complicated balance with regard to statements, 224 | operators, data types etc. For control purposes, I usually made a 225 | special version with output statements that allows to follow the flow of 226 | control. Assertions about the values of variables are provided in the 227 | form of comments in the program, and the following chart shows the 228 | dynamic procedure call chain: 229 | 230 | Main 231 | P0 232 | P5 P4 F2 P7 P8 P1 F1 F1 P2 233 | F1 P3 P6 P7 234 | P7 F3 235 | 236 | 237 | 4.3. Documentation of Results 238 | 239 | In stating results, the configuration used for measurement should be 240 | described as detailed as possible. Relevant data are: Machine version, 241 | language, compiler version, compile options (e.g. "optimize" option, 242 | runtime checks enabled or not). With microprocessors, the clock 243 | frequency and the memory system characteristics (number of wait states) 244 | are necessary for meaningful comparisons. In the case of C, it should 245 | be included whether the "register" attribute has been used, and to which 246 | variables it was applied. (According to my experiences with Berkeley 247 | UNIX C on a VAX 11/780, the times differed somewhat, though not much.) 248 | 249 | 250 | 5. Correspondence 251 | 252 | 253 | For people who want to make measurements with the program and who don't 254 | have access to Usenet, I have prepared floppy disks with the source 255 | files, the data are: Standard size 8", single-sided, double density, 256 | written on an Intel 86/330 in RMX format; these floppy disks are sent in 257 | exchange for an empty floppy disk. (However, this will be irrelevant 258 | for you, the reader of this note posted on Usenet.) 259 | 260 | If you make measurements with the program - whether you obtained the 261 | source file via Usenet, via floppy disk or by re-typing it -, I would 262 | appreciate very much if you could send me the results of your 263 | measurements. I plan to make a comprehensive list of these results for 264 | different machines and compilers and, in the first months of 1985, to 265 | send this list to all who contributed to it. 266 | 267 | For US mail, please use the address 268 | 269 | Reinhold P. Weicker 270 | Siemens Corporate Research and Technology 271 | 105 College Road East 272 | Princeton, NJ 08540 273 | 274 | For electronic mail via UUCP, the address (at present) is 275 | 276 | ...{ihnp4,allegra,decvax}!ogcvax!inteloa!weicker 277 | -------------------------------------------------------------------------------- /v2.0/dhry_pack_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * 4 | * "DHRYSTONE" Benchmark Program 5 | * ----------------------------- 6 | * 7 | * Version: C, Version 2.0 8 | * 9 | * File: dhry_pack_1.c (part 2 of 3) 10 | * 11 | * Date: March 3, 1988 12 | * 13 | * Author: Reinhold P. Weicker 14 | * 15 | **************************************************************************** 16 | */ 17 | 18 | #include "dhry_global.h" 19 | 20 | /* Global Variables: */ 21 | 22 | Rec_Pointer Ptr_Glob, 23 | Next_Ptr_Glob; 24 | int Int_Glob; 25 | Boolean Bool_Glob; 26 | char Ch_1_Glob, 27 | Ch_2_Glob; 28 | int Arr_1_Glob [50]; 29 | int Arr_2_Glob [50] [50]; 30 | 31 | extern char *malloc (); 32 | Enumeration Func_1 (); 33 | /* forward declaration necessary since Enumeration may not simply be int */ 34 | 35 | #ifndef REG 36 | Boolean Reg = false; 37 | #define REG 38 | /* REG becomes defined as empty */ 39 | /* i.e. no register variables */ 40 | #else 41 | Boolean Reg = true; 42 | #endif 43 | 44 | /* variables for time measurement: */ 45 | 46 | #ifdef TIMES 47 | struct tms time_info; 48 | extern int times (); 49 | /* see library function "times" */ 50 | #endif 51 | #ifdef TIME 52 | extern long time(); 53 | /* see library function "time" */ 54 | #endif 55 | 56 | #define Too_Small_Time 2 57 | /* Measurements should last at least 2 seconds */ 58 | 59 | long Begin_Time, 60 | End_Time, 61 | User_Time; 62 | float Microseconds, 63 | Dhrystones_Per_Second; 64 | 65 | /* end of variables for time measurement */ 66 | 67 | 68 | main () 69 | /*****/ 70 | 71 | /* main program, corresponds to procedures */ 72 | /* Main and Proc_0 in the Ada version */ 73 | 74 | { 75 | One_Fifty Int_1_Loc; 76 | REG One_Fifty Int_2_Loc; 77 | One_Fifty Int_3_Loc; 78 | REG char Ch_Index; 79 | Enumeration Enum_Loc; 80 | Str_30 Str_1_Loc; 81 | Str_30 Str_2_Loc; 82 | REG int Run_Index; 83 | REG int Number_Of_Runs; 84 | 85 | 86 | /* Initializations */ 87 | 88 | Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 89 | Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 90 | 91 | Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; 92 | Ptr_Glob->Discr = Ident_1; 93 | Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; 94 | Ptr_Glob->variant.var_1.Int_Comp = 40; 95 | strcpy (Ptr_Glob->variant.var_1.Str_Comp, 96 | "DHRYSTONE PROGRAM, SOME STRING"); 97 | strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); 98 | 99 | Arr_2_Glob [8][7] = 10; 100 | /* Was missing in published program. Without this */ 101 | /* initialization, Arr_2_Glob [8][7] would have an */ 102 | /* undefined value. */ 103 | /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ 104 | /* overflow may occur for this array element. */ 105 | 106 | printf ("\n"); 107 | printf ("Dhrystone Benchmark, Version 2.0 (Language: C)\n"); 108 | printf ("\n"); 109 | if (Reg) 110 | { 111 | printf ("Program compiled with 'register' attribute\n"); 112 | printf ("\n"); 113 | } 114 | else 115 | { 116 | printf ("Program compiled without 'register' attribute\n"); 117 | printf ("\n"); 118 | } 119 | printf ("Please give the number of runs through the benchmark: "); 120 | { 121 | int n; 122 | scanf ("%d", &n); 123 | Number_Of_Runs = n; 124 | } 125 | printf ("\n"); 126 | 127 | printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); 128 | 129 | /***************/ 130 | /* Start timer */ 131 | /***************/ 132 | 133 | #ifdef TIMES 134 | times (&time_info); 135 | Begin_Time = (long) time_info.tms_utime; 136 | #endif 137 | #ifdef TIME 138 | Begin_Time = time ( (long *) 0); 139 | #endif 140 | 141 | for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) 142 | { 143 | 144 | Proc_5(); 145 | Proc_4(); 146 | /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ 147 | Int_1_Loc = 2; 148 | Int_2_Loc = 3; 149 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); 150 | Enum_Loc = Ident_2; 151 | Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); 152 | /* Bool_Glob == 1 */ 153 | while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ 154 | { 155 | Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; 156 | /* Int_3_Loc == 7 */ 157 | Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); 158 | /* Int_3_Loc == 7 */ 159 | Int_1_Loc += 1; 160 | } /* while */ 161 | /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 162 | Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); 163 | /* Int_Glob == 5 */ 164 | Proc_1 (Ptr_Glob); 165 | for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) 166 | /* loop body executed twice */ 167 | { 168 | if (Enum_Loc == Func_1 (Ch_Index, 'C')) 169 | /* then, not executed */ 170 | { 171 | Proc_6 (Ident_1, &Enum_Loc); 172 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 173 | Int_2_Loc = Run_Index; 174 | Int_Glob = Run_Index; 175 | } 176 | } 177 | /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 178 | Int_2_Loc = Int_2_Loc * Int_1_Loc; 179 | Int_1_Loc = Int_2_Loc / Int_3_Loc; 180 | Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; 181 | /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ 182 | Proc_2 (&Int_1_Loc); 183 | /* Int_1_Loc == 5 */ 184 | 185 | } /* loop "for Run_Index" */ 186 | 187 | /**************/ 188 | /* Stop timer */ 189 | /**************/ 190 | 191 | #ifdef TIMES 192 | times (&time_info); 193 | End_Time = (long) time_info.tms_utime; 194 | #endif 195 | #ifdef TIME 196 | End_Time = time ( (long *) 0); 197 | #endif 198 | 199 | printf ("Execution ends\n"); 200 | printf ("\n"); 201 | printf ("Final values of the variables used in the benchmark:\n"); 202 | printf ("\n"); 203 | printf ("Int_Glob: %d\n", Int_Glob); 204 | printf (" should be: %d\n", 5); 205 | printf ("Bool_Glob: %d\n", Bool_Glob); 206 | printf (" should be: %d\n", 1); 207 | printf ("Ch_1_Glob: %c\n", Ch_1_Glob); 208 | printf (" should be: %c\n", 'A'); 209 | printf ("Ch_2_Glob: %c\n", Ch_2_Glob); 210 | printf (" should be: %c\n", 'B'); 211 | printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); 212 | printf (" should be: %d\n", 7); 213 | printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); 214 | printf (" should be: Number_Of_Runs + 10\n"); 215 | printf ("Ptr_Glob->\n"); 216 | printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); 217 | printf (" should be: (implementation-dependent)\n"); 218 | printf (" Discr: %d\n", Ptr_Glob->Discr); 219 | printf (" should be: %d\n", 0); 220 | printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); 221 | printf (" should be: %d\n", 2); 222 | printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); 223 | printf (" should be: %d\n", 17); 224 | printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); 225 | printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 226 | printf ("Next_Ptr_Glob->\n"); 227 | printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); 228 | printf (" should be: (implementation-dependent), same as above\n"); 229 | printf (" Discr: %d\n", Next_Ptr_Glob->Discr); 230 | printf (" should be: %d\n", 0); 231 | printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); 232 | printf (" should be: %d\n", 1); 233 | printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); 234 | printf (" should be: %d\n", 18); 235 | printf (" Str_Comp: %s\n", 236 | Next_Ptr_Glob->variant.var_1.Str_Comp); 237 | printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 238 | printf ("Int_1_Loc: %d\n", Int_1_Loc); 239 | printf (" should be: %d\n", 5); 240 | printf ("Int_2_Loc: %d\n", Int_2_Loc); 241 | printf (" should be: %d\n", 13); 242 | printf ("Int_3_Loc: %d\n", Int_3_Loc); 243 | printf (" should be: %d\n", 7); 244 | printf ("Enum_Loc: %d\n", Enum_Loc); 245 | printf (" should be: %d\n", 1); 246 | printf ("Str_1_Loc: %s\n", Str_1_Loc); 247 | printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); 248 | printf ("Str_2_Loc: %s\n", Str_2_Loc); 249 | printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); 250 | printf ("\n"); 251 | 252 | User_Time = End_Time - Begin_Time; 253 | 254 | if (User_Time < Too_Small_Time) 255 | { 256 | printf ("Measured time too small to obtain meaningful results\n"); 257 | printf ("Please increase number of runs\n"); 258 | printf ("\n"); 259 | } 260 | else 261 | { 262 | #ifdef TIME 263 | Microseconds = (float) User_Time * Mic_secs_Per_Second 264 | / (float) Number_Of_Runs; 265 | Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; 266 | #else 267 | Microseconds = (float) User_Time * Mic_secs_Per_Second 268 | / ((float) HZ * ((float) Number_Of_Runs)); 269 | Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) 270 | / (float) User_Time; 271 | #endif 272 | printf ("Microseconds for one run through Dhrystone: "); 273 | printf ("%6.1f \n", Microseconds); 274 | printf ("Dhrystones per Second: "); 275 | printf ("%6.1f \n", Dhrystones_Per_Second); 276 | printf ("\n"); 277 | } 278 | 279 | } 280 | 281 | 282 | Proc_1 (Ptr_Val_Par) 283 | /**********************/ 284 | 285 | REG Rec_Pointer Ptr_Val_Par; 286 | /* executed once */ 287 | { 288 | REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; 289 | /* == Ptr_Glob_Next */ 290 | /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ 291 | /* corresponds to "rename" in Ada, "with" in Pascal */ 292 | 293 | structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 294 | Ptr_Val_Par->variant.var_1.Int_Comp = 5; 295 | Next_Record->variant.var_1.Int_Comp 296 | = Ptr_Val_Par->variant.var_1.Int_Comp; 297 | Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; 298 | Proc_3 (&Next_Record->Ptr_Comp); 299 | /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp 300 | == Ptr_Glob->Ptr_Comp */ 301 | if (Next_Record->Discr == Ident_1) 302 | /* then, executed */ 303 | { 304 | Next_Record->variant.var_1.Int_Comp = 6; 305 | Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 306 | &Next_Record->variant.var_1.Enum_Comp); 307 | Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; 308 | Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 309 | &Next_Record->variant.var_1.Int_Comp); 310 | } 311 | else /* not executed */ 312 | structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); 313 | } /* Proc_1 */ 314 | 315 | 316 | Proc_2 (Int_Par_Ref) 317 | /******************/ 318 | /* executed once */ 319 | /* *Int_Par_Ref == 1, becomes 4 */ 320 | 321 | One_Fifty *Int_Par_Ref; 322 | { 323 | One_Fifty Int_Loc; 324 | Enumeration Enum_Loc; 325 | 326 | Int_Loc = *Int_Par_Ref + 10; 327 | do /* executed once */ 328 | if (Ch_1_Glob == 'A') 329 | /* then, executed */ 330 | { 331 | Int_Loc -= 1; 332 | *Int_Par_Ref = Int_Loc - Int_Glob; 333 | Enum_Loc = Ident_1; 334 | } /* if */ 335 | while (Enum_Loc != Ident_1); /* true */ 336 | } /* Proc_2 */ 337 | 338 | 339 | Proc_3 (Ptr_Ref_Par) 340 | /**********************/ 341 | /* executed once */ 342 | /* Ptr_Ref_Par becomes Ptr_Glob */ 343 | 344 | Rec_Pointer *Ptr_Ref_Par; 345 | 346 | { 347 | if (Ptr_Glob != Null) 348 | /* then, executed */ 349 | *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; 350 | else /* not executed */ 351 | Int_Glob = 100; 352 | Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); 353 | } /* Proc_3 */ 354 | 355 | 356 | 357 | Proc_4 () /* without parameters */ 358 | /*******/ 359 | /* executed once */ 360 | { 361 | Boolean Bool_Loc; 362 | 363 | Bool_Loc = Ch_1_Glob == 'A'; 364 | Bool_Glob = Bool_Loc | Bool_Glob; 365 | Ch_2_Glob = 'B'; 366 | } /* Proc_4 */ 367 | 368 | 369 | Proc_5 () /* without parameters */ 370 | /*******/ 371 | /* executed once */ 372 | { 373 | Ch_1_Glob = 'A'; 374 | Bool_Glob = false; 375 | } /* Proc_5 */ 376 | 377 | 378 | /* Procedure for the assignment of structures, */ 379 | /* if the C compiler doesn't support this feature */ 380 | #ifdef NOSTRUCTASSIGN 381 | memcpy (d, s, l) 382 | register char *d; 383 | register char *s; 384 | register int l; 385 | { 386 | while (l--) *d++ = *s++; 387 | } 388 | #endif 389 | 390 | 391 | -------------------------------------------------------------------------------- /v2.1/dhry_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * 4 | * "DHRYSTONE" Benchmark Program 5 | * ----------------------------- 6 | * 7 | * Version: C, Version 2.1 8 | * 9 | * File: dhry_1.c (part 2 of 3) 10 | * 11 | * Date: May 25, 1988 12 | * 13 | * Author: Reinhold P. Weicker 14 | * 15 | **************************************************************************** 16 | */ 17 | 18 | #include "dhry.h" 19 | 20 | /* Global Variables: */ 21 | 22 | Rec_Pointer Ptr_Glob, 23 | Next_Ptr_Glob; 24 | int Int_Glob; 25 | Boolean Bool_Glob; 26 | char Ch_1_Glob, 27 | Ch_2_Glob; 28 | int Arr_1_Glob [50]; 29 | int Arr_2_Glob [50] [50]; 30 | 31 | extern char *malloc (); 32 | Enumeration Func_1 (); 33 | /* forward declaration necessary since Enumeration may not simply be int */ 34 | 35 | #ifndef REG 36 | Boolean Reg = false; 37 | #define REG 38 | /* REG becomes defined as empty */ 39 | /* i.e. no register variables */ 40 | #else 41 | Boolean Reg = true; 42 | #endif 43 | 44 | /* variables for time measurement: */ 45 | 46 | #ifdef TIMES 47 | struct tms time_info; 48 | extern int times (); 49 | /* see library function "times" */ 50 | #define Too_Small_Time (2*HZ) 51 | /* Measurements should last at least about 2 seconds */ 52 | #endif 53 | #ifdef TIME 54 | extern long time(); 55 | /* see library function "time" */ 56 | #define Too_Small_Time 2 57 | /* Measurements should last at least 2 seconds */ 58 | #endif 59 | #ifdef MSC_CLOCK 60 | extern clock_t clock(); 61 | #define Too_Small_Time (2*HZ) 62 | #endif 63 | 64 | long Begin_Time, 65 | End_Time, 66 | User_Time; 67 | float Microseconds, 68 | Dhrystones_Per_Second; 69 | 70 | /* end of variables for time measurement */ 71 | 72 | 73 | main () 74 | /*****/ 75 | 76 | /* main program, corresponds to procedures */ 77 | /* Main and Proc_0 in the Ada version */ 78 | { 79 | One_Fifty Int_1_Loc; 80 | REG One_Fifty Int_2_Loc; 81 | One_Fifty Int_3_Loc; 82 | REG char Ch_Index; 83 | Enumeration Enum_Loc; 84 | Str_30 Str_1_Loc; 85 | Str_30 Str_2_Loc; 86 | REG int Run_Index; 87 | REG int Number_Of_Runs; 88 | 89 | /* Initializations */ 90 | 91 | Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 92 | Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type)); 93 | 94 | Ptr_Glob->Ptr_Comp = Next_Ptr_Glob; 95 | Ptr_Glob->Discr = Ident_1; 96 | Ptr_Glob->variant.var_1.Enum_Comp = Ident_3; 97 | Ptr_Glob->variant.var_1.Int_Comp = 40; 98 | strcpy (Ptr_Glob->variant.var_1.Str_Comp, 99 | "DHRYSTONE PROGRAM, SOME STRING"); 100 | strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); 101 | 102 | Arr_2_Glob [8][7] = 10; 103 | /* Was missing in published program. Without this statement, */ 104 | /* Arr_2_Glob [8][7] would have an undefined value. */ 105 | /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */ 106 | /* overflow may occur for this array element. */ 107 | 108 | printf ("\n"); 109 | printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); 110 | printf ("\n"); 111 | if (Reg) 112 | { 113 | printf ("Program compiled with 'register' attribute\n"); 114 | printf ("\n"); 115 | } 116 | else 117 | { 118 | printf ("Program compiled without 'register' attribute\n"); 119 | printf ("\n"); 120 | } 121 | printf ("Please give the number of runs through the benchmark: "); 122 | { 123 | int n; 124 | scanf ("%d", &n); 125 | Number_Of_Runs = n; 126 | } 127 | printf ("\n"); 128 | 129 | printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs); 130 | 131 | /***************/ 132 | /* Start timer */ 133 | /***************/ 134 | 135 | #ifdef TIMES 136 | times (&time_info); 137 | Begin_Time = (long) time_info.tms_utime; 138 | #endif 139 | #ifdef TIME 140 | Begin_Time = time ( (long *) 0); 141 | #endif 142 | #ifdef MSC_CLOCK 143 | Begin_Time = clock(); 144 | #endif 145 | 146 | for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) 147 | { 148 | 149 | Proc_5(); 150 | Proc_4(); 151 | /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ 152 | Int_1_Loc = 2; 153 | Int_2_Loc = 3; 154 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); 155 | Enum_Loc = Ident_2; 156 | Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); 157 | /* Bool_Glob == 1 */ 158 | while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ 159 | { 160 | Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; 161 | /* Int_3_Loc == 7 */ 162 | Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); 163 | /* Int_3_Loc == 7 */ 164 | Int_1_Loc += 1; 165 | } /* while */ 166 | /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 167 | Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); 168 | /* Int_Glob == 5 */ 169 | Proc_1 (Ptr_Glob); 170 | for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) 171 | /* loop body executed twice */ 172 | { 173 | if (Enum_Loc == Func_1 (Ch_Index, 'C')) 174 | /* then, not executed */ 175 | { 176 | Proc_6 (Ident_1, &Enum_Loc); 177 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 178 | Int_2_Loc = Run_Index; 179 | Int_Glob = Run_Index; 180 | } 181 | } 182 | /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ 183 | Int_2_Loc = Int_2_Loc * Int_1_Loc; 184 | Int_1_Loc = Int_2_Loc / Int_3_Loc; 185 | Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; 186 | /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ 187 | Proc_2 (&Int_1_Loc); 188 | /* Int_1_Loc == 5 */ 189 | 190 | } /* loop "for Run_Index" */ 191 | 192 | /**************/ 193 | /* Stop timer */ 194 | /**************/ 195 | 196 | #ifdef TIMES 197 | times (&time_info); 198 | End_Time = (long) time_info.tms_utime; 199 | #endif 200 | #ifdef TIME 201 | End_Time = time ( (long *) 0); 202 | #endif 203 | #ifdef MSC_CLOCK 204 | End_Time = clock(); 205 | #endif 206 | 207 | printf ("Execution ends\n"); 208 | printf ("\n"); 209 | printf ("Final values of the variables used in the benchmark:\n"); 210 | printf ("\n"); 211 | printf ("Int_Glob: %d\n", Int_Glob); 212 | printf (" should be: %d\n", 5); 213 | printf ("Bool_Glob: %d\n", Bool_Glob); 214 | printf (" should be: %d\n", 1); 215 | printf ("Ch_1_Glob: %c\n", Ch_1_Glob); 216 | printf (" should be: %c\n", 'A'); 217 | printf ("Ch_2_Glob: %c\n", Ch_2_Glob); 218 | printf (" should be: %c\n", 'B'); 219 | printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]); 220 | printf (" should be: %d\n", 7); 221 | printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]); 222 | printf (" should be: Number_Of_Runs + 10\n"); 223 | printf ("Ptr_Glob->\n"); 224 | printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp); 225 | printf (" should be: (implementation-dependent)\n"); 226 | printf (" Discr: %d\n", Ptr_Glob->Discr); 227 | printf (" should be: %d\n", 0); 228 | printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp); 229 | printf (" should be: %d\n", 2); 230 | printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp); 231 | printf (" should be: %d\n", 17); 232 | printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp); 233 | printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 234 | printf ("Next_Ptr_Glob->\n"); 235 | printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp); 236 | printf (" should be: (implementation-dependent), same as above\n"); 237 | printf (" Discr: %d\n", Next_Ptr_Glob->Discr); 238 | printf (" should be: %d\n", 0); 239 | printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp); 240 | printf (" should be: %d\n", 1); 241 | printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp); 242 | printf (" should be: %d\n", 18); 243 | printf (" Str_Comp: %s\n", 244 | Next_Ptr_Glob->variant.var_1.Str_Comp); 245 | printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n"); 246 | printf ("Int_1_Loc: %d\n", Int_1_Loc); 247 | printf (" should be: %d\n", 5); 248 | printf ("Int_2_Loc: %d\n", Int_2_Loc); 249 | printf (" should be: %d\n", 13); 250 | printf ("Int_3_Loc: %d\n", Int_3_Loc); 251 | printf (" should be: %d\n", 7); 252 | printf ("Enum_Loc: %d\n", Enum_Loc); 253 | printf (" should be: %d\n", 1); 254 | printf ("Str_1_Loc: %s\n", Str_1_Loc); 255 | printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n"); 256 | printf ("Str_2_Loc: %s\n", Str_2_Loc); 257 | printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n"); 258 | printf ("\n"); 259 | 260 | User_Time = End_Time - Begin_Time; 261 | 262 | if (User_Time < Too_Small_Time) 263 | { 264 | printf ("Measured time too small to obtain meaningful results\n"); 265 | printf ("Please increase number of runs\n"); 266 | printf ("\n"); 267 | } 268 | else 269 | { 270 | #ifdef TIME 271 | Microseconds = (float) User_Time * Mic_secs_Per_Second 272 | / (float) Number_Of_Runs; 273 | Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; 274 | #else 275 | Microseconds = (float) User_Time * Mic_secs_Per_Second 276 | / ((float) HZ * ((float) Number_Of_Runs)); 277 | Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) 278 | / (float) User_Time; 279 | #endif 280 | printf ("Microseconds for one run through Dhrystone: "); 281 | printf ("%6.1f \n", Microseconds); 282 | printf ("Dhrystones per Second: "); 283 | printf ("%6.1f \n", Dhrystones_Per_Second); 284 | printf ("\n"); 285 | } 286 | 287 | } 288 | 289 | 290 | Proc_1 (Ptr_Val_Par) 291 | /******************/ 292 | 293 | REG Rec_Pointer Ptr_Val_Par; 294 | /* executed once */ 295 | { 296 | REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp; 297 | /* == Ptr_Glob_Next */ 298 | /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */ 299 | /* corresponds to "rename" in Ada, "with" in Pascal */ 300 | 301 | structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 302 | Ptr_Val_Par->variant.var_1.Int_Comp = 5; 303 | Next_Record->variant.var_1.Int_Comp 304 | = Ptr_Val_Par->variant.var_1.Int_Comp; 305 | Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp; 306 | Proc_3 (&Next_Record->Ptr_Comp); 307 | /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp 308 | == Ptr_Glob->Ptr_Comp */ 309 | if (Next_Record->Discr == Ident_1) 310 | /* then, executed */ 311 | { 312 | Next_Record->variant.var_1.Int_Comp = 6; 313 | Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 314 | &Next_Record->variant.var_1.Enum_Comp); 315 | Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp; 316 | Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 317 | &Next_Record->variant.var_1.Int_Comp); 318 | } 319 | else /* not executed */ 320 | structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp); 321 | } /* Proc_1 */ 322 | 323 | 324 | Proc_2 (Int_Par_Ref) 325 | /******************/ 326 | /* executed once */ 327 | /* *Int_Par_Ref == 1, becomes 4 */ 328 | 329 | One_Fifty *Int_Par_Ref; 330 | { 331 | One_Fifty Int_Loc; 332 | Enumeration Enum_Loc; 333 | 334 | Int_Loc = *Int_Par_Ref + 10; 335 | do /* executed once */ 336 | if (Ch_1_Glob == 'A') 337 | /* then, executed */ 338 | { 339 | Int_Loc -= 1; 340 | *Int_Par_Ref = Int_Loc - Int_Glob; 341 | Enum_Loc = Ident_1; 342 | } /* if */ 343 | while (Enum_Loc != Ident_1); /* true */ 344 | } /* Proc_2 */ 345 | 346 | 347 | Proc_3 (Ptr_Ref_Par) 348 | /******************/ 349 | /* executed once */ 350 | /* Ptr_Ref_Par becomes Ptr_Glob */ 351 | 352 | Rec_Pointer *Ptr_Ref_Par; 353 | 354 | { 355 | if (Ptr_Glob != Null) 356 | /* then, executed */ 357 | *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp; 358 | Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp); 359 | } /* Proc_3 */ 360 | 361 | 362 | Proc_4 () /* without parameters */ 363 | /*******/ 364 | /* executed once */ 365 | { 366 | Boolean Bool_Loc; 367 | 368 | Bool_Loc = Ch_1_Glob == 'A'; 369 | Bool_Glob = Bool_Loc | Bool_Glob; 370 | Ch_2_Glob = 'B'; 371 | } /* Proc_4 */ 372 | 373 | 374 | Proc_5 () /* without parameters */ 375 | /*******/ 376 | /* executed once */ 377 | { 378 | Ch_1_Glob = 'A'; 379 | Bool_Glob = false; 380 | } /* Proc_5 */ 381 | 382 | 383 | /* Procedure for the assignment of structures, */ 384 | /* if the C compiler doesn't support this feature */ 385 | #ifdef NOSTRUCTASSIGN 386 | memcpy (d, s, l) 387 | register char *d; 388 | register char *s; 389 | register int l; 390 | { 391 | while (l--) *d++ = *s++; 392 | } 393 | #endif 394 | 395 | 396 | -------------------------------------------------------------------------------- /original-sources/1984-11-15-dhrystone-part1: -------------------------------------------------------------------------------- 1 | 2 | Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP 3 | Posting-Version: Notesfiles $Revision: 1.6.2.14 $; site siemens.UUCP 4 | Path: utzoo!watmath!clyde!burl!ulysses!allegra!princeton!eosp1!siemens!bea 5 | From: b...@siemens.UUCP 6 | Newsgroups: net.sources 7 | Subject: Dhrystone benchmark, part 1 pkk, paa 8 | Message-ID: <28600001@siemens.UUCP> 9 | Date: Thu, 15-Nov-84 09:20:00 EST 10 | Article-I.D.: siemens.28600001 11 | Posted: Thu Nov 15 09:20:00 1984 12 | Date-Received: Fri, 16-Nov-84 05:32:59 EST 13 | Lines: 279 14 | Nf-ID: #N:siemens:28600001:000:12017 15 | Nf-From: siemens!bea Nov 15 09:20:00 1984 16 | 17 | 18 | 19 | 20 | MEASUREMENTS WITH THE "DHRYSTONE" BENCHMARK PROGRAM 21 | - USER'S GUIDE - 22 | 23 | REINHOLD P. WEICKER 24 | 25 | OCTOBER 1984 26 | 27 | 28 | 29 | 1. Introduction 30 | 31 | 32 | For "Communication of the ACM", I wrote a paper "Dhrystone: A Synthetic 33 | Systems Programming Benchmark" which appeared in the October issue of 34 | the journal (vol. 27, no. 10, Oct. 1984, p. 1013-1030). The paper 35 | consists of two main parts: First, statistical data about the use of 36 | programming language features (especially in the area of systems 37 | programming) are summarized, and second, a synthetic benchmark program, 38 | written in Ada, is given that is based on these data. 39 | 40 | I am posting the program here in Usenet for those who are interested in 41 | using the "Dhrystone" benchmark program for measurements. The 42 | distribution consists of four parts: 43 | 44 | - Part 1 is this paper (user's guide) containing hints that 45 | should be taken into account when the program is used for 46 | benchmarking, 47 | 48 | - Part 2 is the program (reference version) in Ada, 49 | 50 | - Part 3 is the program (measurement version) in Pascal, 51 | 52 | - Part 4 is the program (measurement version) in C. 53 | 54 | A "reference" version contains just the program text, together with 55 | comments on the statistics, a "measurement" version is a versions where 56 | statements for execution time measurement have been inserted. See 57 | section 4 for more details on measurement methods. 58 | 59 | In the case of Ada, the "reference" versions contains the program text 60 | as published. In the cases of Pascal and C, reference versions (not 61 | distributed here) contain an equivalent program text in these languages. 62 | See the publication for remarks on language issues that have to be 63 | considered when the program is translated to languages other than Ada. 64 | 65 | In the "measurement" versions, some statements (those accessing the 66 | operating system clock) are implementation-dependent. The sample 67 | measurement version given here can be used on Berkeley UNIX systems (4.2 68 | bsd). Of course, for measurements on other systems these statements 69 | have to be changed according to the language library routines available 70 | on these systems. 71 | 72 | The program versions distributed via Usenet contain the program in one 73 | file per programming language, I didn't want to flood the net with too 74 | many versions or with too many small units. However, the understanding 75 | is that the program (Ada and C versions) consists of several modules 76 | (compilation units) that can be compiled separately; see section 3 for a 77 | discussion of compilation and linkage issues (program in one file vs. 78 | program in several files). Versions with the source program in several 79 | files can be obtained easily by "cutting" the program into parts at the 80 | obvious locations. In the case of C, suitable "#include" statements and 81 | an "extern" declaration need to be added. 82 | 83 | Similarly, the reference versions for Pascal and C can be obtained from 84 | the files sent via Usenet by removing the statements for measurement, 85 | the I/O statements and the loops around the main procedure. 86 | 87 | 88 | 89 | 2. Errors / Inconsistencies 90 | 91 | 92 | There are two minor inconsistencies in the published version of the 93 | program which were detected too late for a correction in the published 94 | version: 95 | 96 | - In the comment at the beginning of the function body for 97 | Func_2, the beginning of the string literal should read 98 | "DHRYSTONE PROGRAM, ..." instead of "DHRYSTONE, ..." for both 99 | String_Par_In_1 and String_Par_In_2. 100 | 101 | The code is correct, just the comment text is incorrect; the 102 | two strings are different in the 20th, not in the 12th 103 | character. 104 | 105 | - It can be argued that the first "if" statement in Func_2 106 | should have been formulated 107 | 108 | if Char_Loc >= 'W' and then Char_Loc < 'Z' 109 | 110 | rather than 111 | 112 | if Char_Loc >= 'W' and Char_Loc < 'Z' 113 | 114 | since a programmer writing such a program would only be 115 | interested in the value of the "if" condition as a whole, 116 | there is no need to evaluate "Char_Loc < 'Z'" if "Char_Loc >= 117 | 'W'" evaluates to "false" (however, it doesn't hurt either). 118 | 119 | In the C version of the program, I used for this statement the 120 | operator "&&" (and-then) rather than "&" since in C, different 121 | from Ada and Pascal, "&" forces the compiler to interpret the 122 | result as integer (there is no data type boolean in C) and to 123 | apply a bitwise "and" operation. However, I left the Ada 124 | version as published since I didn't want to change the program 125 | after publication, even if there is now a slight inconsistency 126 | between the Ada and the C version. 127 | 128 | 129 | 130 | 3. Compilation and Linkage Issues 131 | 132 | 133 | 3.1. Ada Version 134 | 135 | The "Dhrystone" program in its original (Ada) version consists of six 136 | library units in the sense of Ada: Two packages (Pack_1 and Pack_2) 137 | consisting of both specification and body, one package (Global_Def) with 138 | specification only, and one subprogram (Main). The package structure is 139 | intended since this is the natural way for programming in Ada. 140 | 141 | As far as benchmarking and execution times are concerned, there can be 142 | systems where calls and data accesses across package boundaries have 143 | execution times different from those within a package. In addition, the 144 | execution time may depend upon the way the program is compiled and 145 | executed; there are two possible ways: 146 | 147 | 148 | 1. the six units are compiled separately and linked together 149 | later, 150 | 151 | 2. the six units are submitted to the compiler in one source 152 | file. 153 | 154 | 155 | For many Ada systems there will be no difference in execution time, as 156 | far as the two compilation models are concerned. However, for some 157 | machines there may be a difference since different representations may 158 | be used for addresses (e.g., 16 bit or 32 bit), depending on the 159 | compilation and linkage model used. 160 | 161 | If there is a difference in execution time, the times for both models 162 | should be measured; model (1) is the one that corresponds more to actual 163 | software development. Ada was explicitly designed for large software 164 | projects that use separate compilation. 165 | 166 | 167 | 3.2. C Version 168 | 169 | C does not have a package structure similar to Ada, but it has features 170 | for independent compilation. Therefore, the same consideration apply as 171 | described above for Ada. 172 | 173 | The program structure of the C version is assumed to be similar to the 174 | Ada version, with the difference that there is no separation between 175 | specification and body, and that "main" and "Proc_0" can be the same 176 | procedure. There are three modules, where module 1 contains constant 177 | definitions and type declarations only, and the two other modules 178 | contain the executable routines of the program: 179 | 180 | 181 | - Module 2 contains the global variables and procedures main, 182 | Proc_1, ..., Proc_5. 183 | 184 | - Module 3 contains procedures Proc_6, ..., Proc_8, and 185 | functions Func_1, ... Func_3. 186 | 187 | 188 | If they are compiled separately, these modules use an "#include" to 189 | refer to the module with the global definitions. 190 | 191 | 192 | 3.3. Pascal Version 193 | 194 | Although many Pascal systems provide features for independent 195 | compilation, this is not part of the ISO or ANSI language standard. 196 | Therefore it is not possible to formulate a portable Pascal version with 197 | several modules, and this set contains only a version with the program 198 | in one source file. 199 | 200 | 201 | 4. Measurement 202 | 203 | 204 | 4.1. Method of Measurement 205 | 206 | For measuring the execution time, I have prepared (Pascal and C) 207 | versions of the program which use the normal method: The program text 208 | between the comments "Start timer" and "Stop timer" is enclosed in a 209 | loop, and the loop is executed often enough that the time can be 210 | measured. (Problems with respect to a cache have been discussed in the 211 | publication.) To get an exact result, the execution time of the same 212 | number of empty loops is subtracted. 213 | 214 | On a single-user system, the output statements inserted in the 215 | measurement versions can be used to measure the elapsed time manually 216 | with a stopwatch. On a multi-user system, this obviously does not give 217 | the expected result unless it is guaranteed that no other process is 218 | running on the system. Fortunately, most programming language 219 | implementations provide a call to a runtime library function with the 220 | name "clock", "runtime", or similar that returns the process-specific 221 | clock, measured in some time unit. 222 | 223 | I used the subroutines "clock" (Pascal) and "times" (C) for measurements 224 | on a VAX 11/780 running Berkeley UNIX (4.2 bsd). It seems that a 225 | certain degree of inaccuracy cannot be avoided due to inaccuracies in 226 | the operating system clock, influences of time slicing, different 227 | mappings of pages to physical memory, etc. As an example, Berkely UNIX 228 | gives for C the value of the clock in two parts, "user time" and "system 229 | time". Although the program does not execute any explicit operating 230 | system calls between the measurement points, the system time is not 0 231 | (it usually lies between 2 and 5 % of the user time). For Pascal, only 232 | a time called "user time" is available. 233 | 234 | 235 | 4.2. Control of Results 236 | 237 | When the program is entered into the computer manually, care should be 238 | taken that no typing errors occur; there is no straightforward 239 | indication that the program executes exactly the statements it is 240 | supposed to execute. I didn't see a reasonable way to have the program 241 | compute result values that can be checked easily, while at the same time 242 | maintaining the complicated balance with regard to statements, 243 | operators, data types etc. For control purposes, I usually made a 244 | special version with output statements that allows to follow the flow of 245 | control. Assertions about the values of variables are provided in the 246 | form of comments in the program, and the following chart shows the 247 | dynamic procedure call chain: 248 | 249 | Main 250 | P0 251 | P5 P4 F2 P7 P8 P1 F1 F1 P2 252 | F1 P3 P6 P7 253 | P7 F3 254 | 255 | 256 | 4.3. Documentation of Results 257 | 258 | In stating results, the configuration used for measurement should be 259 | described as detailed as possible. Relevant data are: Machine version, 260 | language, compiler version, compile options (e.g. "optimize" option, 261 | runtime checks enabled or not). With microprocessors, the clock 262 | frequency and the memory system characteristics (number of wait states) 263 | are necessary for meaningful comparisons. In the case of C, it should 264 | be included whether the "register" attribute has been used, and to which 265 | variables it was applied. (According to my experiences with Berkeley 266 | UNIX C on a VAX 11/780, the times differed somewhat, though not much.) 267 | 268 | 269 | 5. Correspondence 270 | 271 | 272 | For people who want to make measurements with the program and who don't 273 | have access to Usenet, I have prepared floppy disks with the source 274 | files, the data are: Standard size 8", single-sided, double density, 275 | written on an Intel 86/330 in RMX format; these floppy disks are sent in 276 | exchange for an empty floppy disk. (However, this will be irrelevant 277 | for you, the reader of this note posted on Usenet.) 278 | 279 | If you make measurements with the program - whether you obtained the 280 | source file via Usenet, via floppy disk or by re-typing it -, I would 281 | appreciate very much if you could send me the results of your 282 | measurements. I plan to make a comprehensive list of these results for 283 | different machines and compilers and, in the first months of 1985, to 284 | send this list to all who contributed to it. 285 | 286 | For US mail, please use the address 287 | 288 | Reinhold P. Weicker 289 | Siemens Corporate Research and Technology 290 | 105 College Road East 291 | Princeton, NJ 08540 292 | 293 | For electronic mail via UUCP, the address (at present) is 294 | 295 | ...{ihnp4,allegra,decvax}!ogcvax!inteloa!weicker 296 | -------------------------------------------------------------------------------- /v2.1/d_global.s: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | -- 3 | -- "DHRYSTONE" Benchmark Program 4 | -- ----------------------------- 5 | -- 6 | -- Version: Ada, Version 2.1 7 | -- 8 | -- File: d_global.s (part 1 of 6) 9 | -- 10 | -- Date: December 17, 1988 11 | -- 12 | -- Author: Reinhold P. Weicker 13 | -- Siemens AG, AUT E 51 14 | -- Postfach 3220 15 | -- 8520 Erlangen 16 | -- Germany (West) 17 | -- Phone: [+49]-9131-7-20330 18 | -- (8-17 Central European Time) 19 | -- Usenet: ..!mcsun!unido!estevax!weicker 20 | -- 21 | -- Original Version published in "Communications of the ACM" 22 | -- vol. 27., no. 10 (Oct. 1984), pp. 1013 - 1030, 23 | -- together with the statistics on which the distribution 24 | -- of statements etc. is based. 25 | -- 26 | -- In this Ada version, the predefined package TEXT_IO 27 | -- is used for Input/Output. For portability, only 28 | -- Standard Ada language features are used for time 29 | -- measaurement. This means that the procedure "Clock" of 30 | -- package CALENDAR is used to measure the time, 31 | -- even though it returns the elapsed time and not the CPU time. 32 | -- See comments in d_pack_1.b for a discussion of 33 | -- time measurement methods. 34 | -- 35 | -- Collection of Results: 36 | -- Reinhold Weicker (address see above) and 37 | -- 38 | -- Rick Richardson 39 | -- PC Research. Inc. 40 | -- 94 Apple Orchard Drive 41 | -- Tinton Falls, NJ 07724 42 | -- Phone: (201) 389-8963 (9-17 EST) 43 | -- Usenet: ...!uunet!pcrat!rick 44 | -- 45 | -- Please send results to Reinhold Weicker and Rick Richardson. 46 | -- Complete information should be given on hardware and software used. 47 | -- Hardware information includes: Machine type, CPU, type and size 48 | -- of caches; for microprocessors: clock frequency, memory speed 49 | -- (number of wait states). 50 | -- Software information includes: Compiler (and runtime library) 51 | -- manufacturer and version, compilation switches, OS version. 52 | -- The Operating System version may give an indication about the 53 | -- compiler; Dhrystone itself performs no OS calls in the measurement loop. 54 | -- 55 | -- The complete output generated by the program should be mailed 56 | -- such that at least some checks for correctness can be made. 57 | -- 58 | ------------------------------------------------------------------------ 59 | -- 60 | -- History: This version Ada/2.1 has been made for two reasons: 61 | -- 62 | -- 1) As far as it is possible without changes to the Dhrystone 63 | -- statistics, optimizing compilers should be prevented from 64 | -- removing significant statements. 65 | -- 66 | -- 2) With the new (2.1) C and Pascal versions, there should 67 | -- be a corresponding Ada version. Also, the Ada version of 68 | -- Dhrystone has not yet found a network distribution comparable 69 | -- to the C version (version 1.1) distributed by Rick Richardson. 70 | -- 71 | -- This Ada version 2.1 has been made consistent with the 72 | -- C version 2.1; therefore the acknowledgments for the C version 73 | -- are due for the Ada version as well: I thank 74 | -- Rick Richardson (Tinton Falls, NJ), Chaim Benedelac (Nat. 75 | -- Semi.), David Ditzel (SUN), Earl Killian and John Mashey (MIPS), 76 | -- Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) 77 | -- for their help with comments on earlier versions of the 78 | -- benchmark. 79 | -- 80 | -- Changes: In the initialization part, this version follows mostly 81 | -- Rick Richardson's C version distributed via Usenet, not the 82 | -- version distributed earlier via floppy disk by Reinhold Weicker. 83 | -- Inside the measurement loop, this version follows the 84 | -- version previously distributed by Reinhold Weicker. 85 | -- 86 | -- At several places in the benchmark, code has been added, 87 | -- but within the measurement loop only in branches that 88 | -- are not executed. The intention is that optimizing compilers 89 | -- should be prevented from moving code out of the measurement 90 | -- loop, or from removing code altogether. Since the statements 91 | -- that are executed within the measurement loop have NOT been 92 | -- changed, the numbers defining the "Dhrystone distribution" 93 | -- (distribution of statements, operand types and locality) 94 | -- still hold. Except for sophisticated optimizing compilers, 95 | -- execution times for this version should be the same as 96 | -- for previous versions. 97 | -- 98 | -- Since it has proven difficult to subtract the time for the 99 | -- measurement loop overhead in a correct way, the loop check 100 | -- has been made a part of the benchmark. This does have 101 | -- an impact - though a very minor one - on the distribution 102 | -- statistics which have been updated for this version. 103 | -- 104 | -- All changes within the measurement loop are described 105 | -- and discussed in the companion paper "Rationale for 106 | -- Dhrystone version 2". 107 | -- 108 | -- Because of the self-imposed limitation that the order and 109 | -- distribution of the executed statements should not be 110 | -- changed, there are still cases where optimizing compilers 111 | -- may not generate code for some statements. To a certain 112 | -- degree, this is unavoidable for small synthetic benchmarks. 113 | -- Users of the benchmark are advised to check code listings 114 | -- whether code is generated for all statements of Dhrystone. 115 | -- 116 | ------------------------------------------------------------------------ 117 | -- 118 | -- Compilation model and measurement (IMPORTANT): 119 | -- 120 | -- This Ada version of Dhrystone consists of six files 121 | -- (file names shortened to 8 characters for MS-DOS floppy disk distribution): 122 | -- 123 | -- - d_global.s (this file, containing global definitions and comments) 124 | -- - d_pack_1.s (containing the package specification of Pack_1) 125 | -- - d_pack_2.s (containing the package specification of Pack_2) 126 | -- - d_pack_1.b (containing the package body of Pack_1) 127 | -- - d_pack_2.b (containing the package body of Pack_2) 128 | -- - d_main.b (containing procedure "main", very short) 129 | -- 130 | -- The following "ground rules" apply for measurements: 131 | -- - Separate compilation 132 | -- - No procedure merging 133 | -- - Otherwise, compiler optimizations are allowed but should be indicated 134 | -- - Default results are those without register declarations 135 | -- See the companion paper "Rationale for Dhrystone Version 2" for a more 136 | -- detailed discussion of these ground rules. 137 | -- 138 | -- For 16-Bit processors (e.g. 80186, 80286), times for all compilation 139 | -- models ("small", "medium", "large" etc.) should be given if possible, 140 | -- together with a definition of these models for the compiler system used. 141 | -- 142 | -------------------------------------------------------------------------------- 143 | -- 144 | -- [Comment from the first distribution, still valid in principle. 145 | -- Note that because of the inclusion of the measurement loop iteration, 146 | -- the numbers are slightly different from the published version.] 147 | -- 148 | -- The following program contains statements of a high level programming 149 | -- language (here: Ada) in a distribution considered representative: 150 | -- 151 | -- assignments 53 % 152 | -- control statements 32 % 153 | -- procedure, function calls 15 % 154 | -- 155 | -- 100 statements are dynamically executed. The program is balanced with 156 | -- respect to the three aspects: 157 | -- 158 | -- - statement type 159 | -- - operand type (for simple data types) 160 | -- - operand access 161 | -- operand global, local, parameter, or constant. 162 | -- 163 | -- The combination of these three aspects is balanced only approximately. 164 | -- 165 | -- 1. Statement Type: 166 | -- ----------------- number 167 | -- 168 | -- V1 := V2 10 169 | -- V := Constant 12 170 | -- (incl. V1 := F( 171 | -- Assignment, 7 172 | -- with array element 173 | -- Assignment, 6 174 | -- with record component 175 | -- -- 176 | -- 35 35 177 | -- 178 | -- X := Y +|-|and|or Z 5 179 | -- X := Y +|-|"=" Constant 6 180 | -- X := X +|- 1 3 181 | -- X := Y *|/ Z 2 182 | -- X := Expression, 1 183 | -- two operators 184 | -- X := Expression, 1 185 | -- three operators 186 | -- -- 187 | -- 18 18 188 | -- 189 | -- if .... then .... 14 190 | -- with "else" 7 191 | -- without "else" 7 192 | -- executed 3 193 | -- not executed 4 194 | -- for ... loop 7 | counted every time 195 | -- while ... loop 4 | the loop condition 196 | -- loop .... exit 1 | is evaluated 197 | -- case ... end case 1 198 | -- return 5 199 | -- rename 1 200 | -- -- 201 | -- 33 33 202 | -- 203 | -- P (...) proced. call 10 204 | -- same package 5 205 | -- other package 5 206 | -- 207 | -- X := F ( 208 | -- function call 5 209 | -- same package 2 210 | -- other package 3 211 | -- -- 212 | -- 15 15 213 | -- --- 214 | -- 101 215 | -- 216 | -- 22 of the 58 assignments have a variable of a constrained 217 | -- (sub-)type as their destination. In general, discriminant checks 218 | -- will be necessary in these cases; however, the compiler may 219 | -- optimize out some of these checks. 220 | -- 221 | -- The average number of parameters in procedure or function calls 222 | -- is 1.80 (not counting the function values as implicit parameters) 223 | -- 224 | -- 225 | -- 2. Operators 226 | -- ------------ 227 | -- number approximate 228 | -- percentage 229 | -- 230 | -- Arithmetic 27 52.9 231 | -- 232 | -- + 16 31.4 233 | -- - 7 13.7 234 | -- * 3 5.9 235 | -- / 1 2.0 236 | -- 237 | -- Comparison 20 39.2 238 | -- 239 | -- = 9 17.6 240 | -- /= 4 7.8 241 | -- > 1 2.0 242 | -- < 3 5.9 243 | -- >= 1 2.0 244 | -- <= 2 3.9 245 | -- 246 | -- Logic 4 7.8 247 | -- 248 | -- AND 1 2.0 249 | -- OR 1 2.0 250 | -- NOT 2 3.9 251 | -- 252 | -- -- ----- 253 | -- 51 99.9 254 | -- 255 | -- 256 | -- 3. Operand Type (counted once per operand reference) 257 | -- --------------- 258 | -- number approximate 259 | -- percentage 260 | -- 261 | -- Integer 135 55.1 % 262 | -- Character 47 19.2 % 263 | -- Enumeration 30 12.2 % 264 | -- Boolean 11 4.5 % 265 | -- Pointer 12 5.0 % 266 | -- String30 6 2.4 % 267 | -- Array 2 0.8 % 268 | -- Record 2 0.8 % 269 | -- --- ------- 270 | -- 245 100.0 % 271 | -- 272 | -- When there is an access path leading to the final operand (e.g. a record 273 | -- component), only the final data type on the access path is counted. 274 | -- 275 | -- There are 16 accesses to components of a record, 9 of them go to 276 | -- a component in a variant part. For some of these accesses, the 277 | -- compiler may suppress generation of code checking the tag field 278 | -- during optimization. 279 | -- 280 | -- 281 | -- 3. Operand Locality: 282 | -- ------------------- 283 | -- 284 | -- local variable 120 49.0 % 285 | -- global variable 20 8.2 % 286 | -- same package 19 7.8 % 287 | -- other package 1 0.4 % 288 | -- parameter 45 18.3 % 289 | -- in 27 11.0 % 290 | -- inout 12 5.0 % 291 | -- out 6 2.4 % 292 | -- function result 5 2.0 % 293 | -- constant 55 22.4 % 294 | -- --- ------- 295 | -- 245 99.9 % 296 | -- 297 | -- 298 | -- There may be cases where a highly optimizing compiler may recognize 299 | -- unnecessary statements and may not generate code for them. 300 | -- 301 | -- There has been no explicit effort to account for the effects of a 302 | -- cache, or to balance the use of long or short displacements for code or 303 | -- data. 304 | -- 305 | -- The program does not compute anything meaningful, but it is syntactically 306 | -- and semantically correct. All variables have a value assigned to them 307 | -- before they are used as a source operand. 308 | -- 309 | -------------------------------------------------------------------------------- 310 | 311 | package Global_Def is 312 | ------------------ 313 | 314 | -- Global type definitions 315 | 316 | type Enumeration is (Ident_1, Ident_2, Ident_3, Ident_4, Ident_5); 317 | 318 | subtype One_To_Thirty is integer range 1..30; 319 | subtype One_To_Fifty is integer range 1..50; 320 | subtype Capital_Letter is character range 'A'..'Z'; 321 | 322 | type String_30 is array (One_To_Thirty) of character; 323 | pragma Pack (String_30); 324 | -- This pragma may be omitted if it leads to a packing of a character 325 | - in less than an 8-bit byte. 326 | 327 | type Array_1_Dim_Integer is array (One_To_Fifty) of integer; 328 | type Array_2_Dim_Integer is array (One_To_Fifty, 329 | One_To_Fifty) of integer; 330 | 331 | type Record_Type (Discr: Enumeration := Ident_1); 332 | type Record_Pointer is access Record_Type; 333 | 334 | type Record_Type (Discr: Enumeration := Ident_1) is 335 | record 336 | Pointer_Comp: Record_Pointer; 337 | case Discr is 338 | when Ident_1 => -- only this variant is used, 339 | -- but in some cases discriminant 340 | -- checks are necessary 341 | Enum_Comp: Enumeration; 342 | Int_Comp: One_To_Fifty; 343 | String_Comp: String_30; 344 | when Ident_2 => 345 | Enum_Comp_2: Enumeration; 346 | String_Comp_2: String_30; 347 | when others => 348 | Char_Comp_1, 349 | Char_Comp_2: character; 350 | end case; 351 | end record; 352 | 353 | end Global_Def; 354 | -------------------------------------------------------------------------------- /v1/global_def.ads: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- -- 3 | -- "DHRYSTONE" Benchmark Program -- 4 | -- ----------------------------- -- 5 | -- -- 6 | -- Version: ADA / 1 (Reference version, all parts in one file) -- 7 | -- -- 8 | -- File: dhry-ref-all.a -- 9 | -- -- 10 | -- Date: Oct. 1984 -- 11 | -- -- 12 | -- Author: Reinhold P. Weicker -- 13 | -- -- 14 | -------------------------------------------------------------------------------- 15 | -- -- 16 | -- The following program contains statements of a high level programming -- 17 | -- language (here: Ada) in a distribution considered representative: -- 18 | -- -- 19 | -- assignments 53 % -- 20 | -- control statements 32 % -- 21 | -- procedure, function calls 15 % -- 22 | -- -- 23 | -- 100 statements are dynamically executed. The program is balanced with -- 24 | -- respect to the three aspects: -- 25 | -- -- 26 | -- - statement type -- 27 | -- - operand type (for simple data types) -- 28 | -- - operand access -- 29 | -- operand global, local, parameter, or constant. -- 30 | -- -- 31 | -- The combination of these three aspects is balanced only approximately. -- 32 | -- -- 33 | -- 1. Statement Type: -- 34 | -- ----------------- number (= percentage) -- 35 | -- -- 36 | -- V1 := V2 10 -- 37 | -- V := Constant 12 -- 38 | -- (incl. V1 := F(..) -- 39 | -- Assignment, 7 -- 40 | -- with array element -- 41 | -- Assignment, 6 -- 42 | -- with record component -- 43 | -- -- -- 44 | -- 35 35 -- 45 | -- -- 46 | -- X := Y +|-|and|or Z 5 -- 47 | -- X := Y +|-|"=" Constant 6 -- 48 | -- X := X +|- 1 3 -- 49 | -- X := Y *|/ Z 2 -- 50 | -- X := Expression, 1 -- 51 | -- two operators -- 52 | -- X := Expression, 1 -- 53 | -- three operators -- 54 | -- -- -- 55 | -- 18 18 -- 56 | -- -- 57 | -- if .... then .... 14 -- 58 | -- with "else" 7 -- 59 | -- without "else" 7 -- 60 | -- executed 3 -- 61 | -- not executed 4 -- 62 | -- for ... loop 6 | counted every time -- 63 | -- while ... loop 4 | the loop condition -- 64 | -- loop .... exit 1 | is evaluated -- 65 | -- case ... end case 1 -- 66 | -- return 5 -- 67 | -- rename 1 -- 68 | -- -- -- 69 | -- 32 32 -- 70 | -- -- 71 | -- P (...) proced. call 10 -- 72 | -- same package 5 -- 73 | -- other package 5 -- 74 | -- -- 75 | -- X := F (...) -- 76 | -- function call 5 -- 77 | -- same package 2 -- 78 | -- other package 3 -- 79 | -- -- -- 80 | -- 15 15 -- 81 | -- --- -- 82 | -- 100 -- 83 | -- -- 84 | -- 22 of the 58 assignments have a variable of a constrained -- 85 | -- (sub-)type as their destination. In general, discriminant checks -- 86 | -- will be necessary in these cases; however, the compiler may -- 87 | -- optimize out some of these checks. -- 88 | -- -- 89 | -- The average number of parameters in procedure or function calls -- 90 | -- is 1.80 (not counting the function values as implicit parameters). -- 91 | -- -- 92 | -- -- 93 | -- 2. Operators -- 94 | -- ------------ -- 95 | -- number approximate -- 96 | -- percentage -- 97 | -- -- 98 | -- Arithmetic 27 52.9 -- 99 | -- -- 100 | -- + 16 31.4 -- 101 | -- - 7 13.7 -- 102 | -- * 3 5.9 -- 103 | -- / 1 2.0 -- 104 | -- -- 105 | -- Comparison 20 39.2 -- 106 | -- -- 107 | -- = 9 17.6 -- 108 | -- /= 4 7.8 -- 109 | -- > 1 2.0 -- 110 | -- < 3 5.9 -- 111 | -- >= 1 2.0 -- 112 | -- <= 2 3.9 -- 113 | -- -- 114 | -- Logic 4 7.8 -- 115 | -- -- 116 | -- AND 1 2.0 -- 117 | -- OR 1 2.0 -- 118 | -- NOT 2 3.9 -- 119 | -- -- 120 | -- -- ----- -- 121 | -- 51 99.9 -- 122 | -- -- 123 | -- -- 124 | -- 3. Operand Type (counted once per operand reference): -- 125 | -- --------------- -- 126 | -- number approximate -- 127 | -- percentage -- 128 | -- -- 129 | -- Integer 131 54.4 % -- 130 | -- Character 47 19.5 % -- 131 | -- Enumeration 31 12.4 % -- 132 | -- Boolean 11 5.0 % -- 133 | -- Pointer 12 4.6 % -- 134 | -- String30 6 2.5 % -- 135 | -- Array 2 0.8 % -- 136 | -- Record 2 0.8 % -- 137 | -- --- ------- -- 138 | -- 241 100.0 % -- 139 | -- -- 140 | -- When there is an access path leading to the final operand (e.g. a record -- 141 | -- component), only the final data type on the access path is counted. -- 142 | -- -- 143 | -- There are 16 accesses to components of a record, 9 of them go to -- 144 | -- a component in a variant part. For some of these accesses, the -- 145 | -- compiler may suppress generation of code checking the tag field -- 146 | -- during optimization. -- 147 | -- -- 148 | -- -- 149 | -- 3. Operand Locality: -- 150 | -- ------------------- -- 151 | -- -- 152 | -- local variable 117 48.5 % -- 153 | -- global variable 19 7.9 % -- 154 | -- same package 18 11.2 % -- 155 | -- other package 1 0.4 % -- 156 | -- parameter 45 18.7 % -- 157 | -- in 27 11.2 % -- 158 | -- inout 12 5.0 % -- 159 | -- out 6 2.5 % -- 160 | -- function result 5 2.1 % -- 161 | -- constant 55 22.8 % -- 162 | -- --- ------- -- 163 | -- 243 100.0 % -- 164 | -- -- 165 | -- -- 166 | -- There may be cases where a highly optimizing compiler may recognize -- 167 | -- unnecessary statements and may not generate code for them. -- 168 | -- -- 169 | -- There has been no explicit effort to account for the effects of a -- 170 | -- cache, or to balance the use of long or short displacements for code or -- 171 | -- data. -- 172 | -- -- 173 | -- The program does not compute anything meaningful, but it is syntactically -- 174 | -- and semantically correct. All variables have a value assigned to them -- 175 | -- before they are used as a source operand. -- 176 | -- -- 177 | -------------------------------------------------------------------------------- 178 | -- -- 179 | -- The "Dhrystone" program consists of six library units in the sense of -- 180 | -- Ada: Two packages (Pack_1 and Pack_2) consisting of both specification -- 181 | -- and body, one package (Global_Def) with specification only, and one -- 182 | -- procedure (Main). The package structure is intended since this is the -- 183 | -- natural ways for programming in Ada, and there can be systems where -- 184 | -- calls and data accesses across package boundaries have execution -- 185 | -- times different from those within a package. -- 186 | -- In addition, the execution time may depend upon the way the program -- 187 | -- is compiled and executed; there are two possible ways: -- 188 | -- (1) the six units are compiled separately and linked together later, -- 189 | -- (2) the six units are submitted to the compiler in one source file. -- 190 | -- -- 191 | -- For many Ada systems there will be no difference in execution time, -- 192 | -- as far as the two compilation models are concerned. -- 193 | -- However, for some machines there may be a difference since different -- 194 | -- representations may be used for addresses (16 bit or 32 bit), depending -- 195 | -- on the compilation model used. -- 196 | -- -- 197 | -- If there is a difference in execution time, the times for both models -- 198 | -- should be measured; model (1) is the one that corresponds more to actual -- 199 | -- software development. Ada was explicitly designed for large software -- 200 | -- projects that use separate compilation. -- 201 | -- -- 202 | -- This file contains the "reference" version of Dhrystone/Ada (i.e. no -- 203 | -- statement for measurement are included), with the whole program in -- 204 | -- one file. For a version with separate source files for all library -- 205 | -- units, see the files dhry-ref-pt1.ada, ..., dhry-ref-pt6.ada. -- 206 | -- -- 207 | -------------------------------------------------------------------------------- 208 | 209 | package Global_Def is 210 | ------------------ 211 | 212 | -- Global type definitions 213 | 214 | type Enumeration is (Ident_1, Ident_2, Ident_3, Ident_4, Ident_5); 215 | 216 | subtype One_To_Thirty is integer range 1..30; 217 | subtype One_To_Fifty is integer range 1..50; 218 | subtype Capital_Letter is character range 'A'..'Z'; 219 | 220 | type String_30 is array (One_To_Thirty) of character; 221 | pragma Pack (String_30); 222 | 223 | type Array_1_Dim_Integer is array (One_To_Fifty) of integer; 224 | type Array_2_Dim_Integer is array (One_To_Fifty, 225 | One_To_Fifty) of integer; 226 | 227 | type Record_Type (Discr: Enumeration := Ident_1); 228 | 229 | type Record_Pointer is access Record_Type; 230 | 231 | type Record_Type (Discr: Enumeration := Ident_1) is 232 | record 233 | Pointer_Comp: Record_Pointer; 234 | case Discr is 235 | when Ident_1 => -- only this variant is used, 236 | -- but in some cases discriminant 237 | -- checks are necessary 238 | Enum_Comp: Enumeration; 239 | Int_Comp: One_To_Fifty; 240 | String_Comp: String_30; 241 | when Ident_2 => 242 | Enum_Comp_2: Enumeration; 243 | String_Comp_2: String_30; 244 | when others => 245 | Char_Comp_1, 246 | Char_Comp_2: character; 247 | end case; 248 | end record; 249 | 250 | end Global_Def; 251 | -------------------------------------------------------------------------------- /v2.0/README: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dhrystone Benchmark: Rationale for Version 2 and Measurement Rules 4 | 5 | 6 | Reinhold P. Weicker 7 | Siemens AG, E STE 35 8 | Postfach 3240 9 | D-8520 Erlangen 10 | Germany (West) 11 | 12 | 13 | 14 | 15 | 1. Why a Version 2 of Dhrystone? 16 | 17 | The Dhrystone benchmark program [1] has become a popular benchmark for 18 | CPU/compiler performance measurement, in particular in the area of 19 | minicomputers, workstations, PC's and microprocesors. It apparently 20 | satisfies a need for an easy-to-use integer benchmark; it gives a first 21 | performance indication which is more meaningful than MIPS numbers 22 | which, in their literal meaning (million instructions per second), 23 | cannot be used across different instruction sets (e.g. RISC vs. CISC). 24 | With the increasing use of the benchmark, it seems necessary to 25 | reconsider the benchmark and to check whether it can still fulfill this 26 | function. Version 2 of Dhrystone is the result of such a re- 27 | evaluation, it has been made for two reasons: 28 | 29 | o Dhrystone has been published in Ada [1], and Versions in Ada, Pascal 30 | and C have been distributed by Reinhold Weicker via floppy disk. 31 | However, the version that was used most often for benchmarking has 32 | been the version made by Rick Richardson by another translation from 33 | the Ada version into the C programming language, this has been the 34 | version distributed via the UNIX network Usenet [2]. 35 | 36 | There is an obvious need for a common C version of Dhrystone, since C 37 | is at present the most popular system programming language for the 38 | class of systems (microcomputers, minicomputers, workstations) where 39 | Dhrystone is used most. There should be, as far as possible, only 40 | one C version of Dhrystone such that results can be compared without 41 | restrictions. In the past, the C versions distributed by Rick 42 | Richardson (Version 1.1) and by Reinhold Weicker had small (though 43 | not significant) differences. 44 | 45 | Together with the new C version, the Ada and Pascal versions have 46 | been updated as well. 47 | 48 | o As far as it is possible without changes to the Dhrystone statistics, 49 | optimizing compilers should be prevented from removing significant 50 | statements. It has turned out in the past that optimizing compilers 51 | suppressed code generation for too many statements (by "dead code 52 | removal" or "dead variable elimination"). This has lead to the 53 | danger that benchmarking results obtained by a naive application of 54 | Dhrystone - without inspection of the code that was generated - could 55 | become meaningless. 56 | 57 | The overall policiy for version 2 has been that the distribution of 58 | statements, operand types and operand locality described in [1] should 59 | remain unchanged as much as possible. (Very few changes were 60 | necessary; their impact should be negligible.) Also, the order of 61 | statements should remain unchanged. Although I am aware of some 62 | critical remarks on the benchmark - I agree with several of them - and 63 | know some suggestions for improvement, I didn't want to change the 64 | benchmark into something different from what has become known as 65 | "Dhrystone"; the confusion generated by such a change would probably 66 | outweight the benefits. If I were to write a new benchmark program, I 67 | wouldn't give it the name "Dhrystone" since this denotes the program 68 | published in [1]. However, I do recognize the need for a larger number 69 | of representative programs that can be used as benchmarks; users should 70 | always be encouraged to use more than just one benchmark. 71 | 72 | The new versions (version 2.0 for C, Pascal and Ada) will be 73 | distributed as widely as possible. Readers who want to use the 74 | benchmark for their own measurements can obtain a copy in machine- 75 | readable form on floppy disk (MS-DOS or XENIX format) from the author. 76 | In addition, the new versions have been posted to the UNIX network 77 | Usenet. 78 | 79 | 80 | 2. Overall Characteristics of Version 2 81 | 82 | In general, version 2 follows - in the parts that are significant for 83 | performance measurement, i.e. within the measurement loop - the 84 | published (Ada) version and the C versions previously distributed. 85 | Where the versions distributed by Rick Richardson [2] and Reinhold 86 | Weicker have been different, it follows the version distributed by 87 | Reinhold Weicker. (However, the differences have been so small that 88 | their impact on execution time in all likelihood has been negligible.) 89 | The initialization and UNIX instrumentation part - which had been 90 | omitted in [1] - follows mostly the ideas of Rick Richardson [2]. 91 | However, any changes in the initialization part and in the printing of 92 | the result have no impact on performance measurement since they are 93 | outside the measaurement loop. As a concession to older compilers, 94 | names have been made unique within the first 8 characters for the C 95 | version. 96 | 97 | The original publication of Dhrystone did not contain any statements 98 | for time measurement since they are necessarily system-dependent. 99 | However, it turned out that it is not enough just to inclose the main 100 | procedure of Dhrystone in a loop and to measure the execution time. If 101 | the variables that are computed are not used somehow, there is the 102 | danger that the compiler considers them as "dead variables" and 103 | suppresses code generation for a part of the statements. Therefore in 104 | version 2 all variables of "main" are printed at the end of the 105 | program. This also permits some plausibility control for correct 106 | execution of the benchmark. 107 | 108 | At several places in the benchmark, code has been added, but only in 109 | branches that are not executed. The intention is that optimizing 110 | compilers should be prevented from moving code out of the measurement 111 | loop, or from removing code altogether. Statements that are executed 112 | have been changed in very few places only. In these cases, only the 113 | role of some operands has been changed, and it was made sure that the 114 | numbers defining the "Dhrystone distribution" (distribution of 115 | statements, operand types and locality) still hold as much as possible. 116 | Except for sophisticated optimizing compilers, execution times for 117 | version 2.0 should be the same as for previous versions. 118 | 119 | Because of the self-imposed limitation that the order and distribution 120 | of the executed statements should not be changed, there are still cases 121 | where optimizing compilers may not generate code for some statements. 122 | To a certain degree, this is unavoidable for small synthetic 123 | benchmarks. Users of the benchmark are advised to check code listings 124 | whether code is generated for all statements of Dhrystone. 125 | 126 | Contrary to the suggestion in the published paper and its realization 127 | in the versions previously distributed, no attempt has been made to 128 | subtract the time for the measurement loop overhead. (This calculation 129 | has proven difficult to implement in a correct way, and its omission 130 | makes the program simpler.) However, since the loop check is now part 131 | of the benchmark, this does have an impact - though a very minor one - 132 | on the distribution statistics which have been updated for this 133 | version. 134 | 135 | 136 | 3. Discussion of Individual Changes 137 | 138 | In this section, all changes are described that affect the measurement 139 | loop and that are not just renamings of variables. All remarks refer to 140 | the C version; the other language versions have been updated similarly. 141 | 142 | In addition to adding the measurement loop and the printout statements, 143 | changes have been made at the following places: 144 | 145 | o In procedure "main", three statements have been added in the non- 146 | executed "then" part of the statement 147 | 148 | if (Enum_Loc == Func_1 (Ch_Index, 'C')) 149 | 150 | they are 151 | 152 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 153 | Int_2_Loc = Run_Index; 154 | Int_Glob = Run_Index; 155 | 156 | The string assignment prevents movement of the preceding assignment 157 | to Str_2_Loc (5'th statement of "main") out of the measurement loop 158 | (This probably will not happen for the C version, but it did happen 159 | with another language and compiler.) The assignment to Int_2_Loc 160 | prevents value propagation for Int_2_Loc, and the assignment to 161 | Int_Glob makes the value of Int_Glob possibly dependent from the 162 | value of Run_Index. 163 | 164 | o In the three arithmetic computations at the end of the measurement 165 | loop in "main ", the role of some variables has been exchanged, to 166 | prevent the division from just cancelling out the multiplication as 167 | it was in [1]. A very smart compiler might have recognized this and 168 | suppressed code generation for the division. 169 | 170 | o For Proc_2, no code has been changed, but the values of the actual 171 | parameter have changed due to changes in "main". 172 | 173 | o In Proc_4, the second assignment has been changed from 174 | 175 | Bool_Loc = Bool_Loc | Bool_Glob; 176 | 177 | to 178 | 179 | Bool_Glob = Bool_Loc | Bool_Glob; 180 | 181 | It now assigns a value to a global variable instead of a local 182 | variable (Bool_Loc); Bool_Loc would be a "dead variable" which is not 183 | used afterwards. 184 | 185 | o In Func_1, the statement 186 | 187 | Ch_1_Glob = Ch_1_Loc; 188 | 189 | was added in the non-executed "else" part of the "if" statement, to 190 | prevent the suppression of code generation for the assignment to 191 | Ch_1_Loc. 192 | 193 | o In Func_2, the second character comparison statement has been changed 194 | to 195 | 196 | if (Ch_Loc == 'R') 197 | 198 | ('R' instead of 'X') because a comparison with 'X' is implied in the 199 | preceding "if" statement. 200 | 201 | Also in Func_2, the statement 202 | 203 | Int_Glob = Int_Loc; 204 | 205 | has been added in the non-executed part of the last "if" statement, 206 | in order to prevent Int_Loc from becoming a dead variable. 207 | 208 | The distribution statistics have been changed only by the addition of 209 | the measurement loop iteration (1 additional statement, 4 additional 210 | local integer operands) and by the change in Proc_4 (one operand 211 | changed from local to global). The distribution statistics in the 212 | comment headers have been updated accordingly. 213 | 214 | 215 | 4. String Operations 216 | 217 | The string operations (string assignment and string comparison) have 218 | not been changed, to keep the program consistent with the original 219 | version. 220 | 221 | There has been some concern that the string operations are over- 222 | represented in the program, and that execution time is dominated by 223 | these operations. This was true in particular when optimizing 224 | compilers removed too much code in the main part of the program, this 225 | should have been mitigated in version 2. 226 | 227 | It should be noted that this is a language-dependent issue: Dhrystone 228 | was first published in Ada, and with Ada or Pascal semantics, the time 229 | spent in the string operations is, at least in all implementations 230 | known to me, considerably smaller. In Ada and Pascal, assignment and 231 | comparison of strings are operators defined in the language, and the 232 | upper bounds of the strings occuring in Dhrystone are part of the type 233 | information known at compilation time. The compilers can therefore 234 | generate efficient inline code. In C, string assignemt and comparisons 235 | are not part of the language, so the C library functions "strcpy" and 236 | "strcmp" have to be used. In addition to the overhead caused by two 237 | additional function calls, these functions are defined for null- 238 | terminated strings where the length of the strings is not known at 239 | compilation time; the function has to check every byte for the 240 | termination condition (the null byte). 241 | 242 | Obviously, a C library which includes efficiently coded "strcpy" and 243 | "strcmp" functions helps to obtain good Dhrystone results. However, I 244 | don't think that this is unfair since string functions do occur quite 245 | frequently in real programs (editors, command interpreters, etc.). If 246 | the strings functions are implemented efficiently, this helps real 247 | programs as well as benchmark programs. 248 | 249 | I admit that the string comparison in Dhrystone terminates later (after 250 | scanning 20 characters) than most string comparisons in real programs. 251 | For consistency with the original benchmark, I didn't change the 252 | program despite this weakness. 253 | 254 | 255 | 5. Intended Use of Dhrystone 256 | 257 | When Dhrystone is used, the following "ground rules" apply: 258 | 259 | o Separate compilation (Ada and C versions) 260 | 261 | As mentioned in [1], Dhrystone was written to reflect actual 262 | programming practice in systems programming. The division into 263 | several compilation units (5 in the Ada version, 3 in the C version) 264 | is intended, as is the distribution of inter-module and intra-module 265 | subprogram calls. Although on many systems there will be no 266 | difference in execution time to a Dhrystone version where all 267 | compilation units are merged into one file, the rule is that separate 268 | compilation should be used. The intention is that real programming 269 | practice, where programs consist of several independently compiled 270 | units, should be reflected. This also has implies that the compiler, 271 | while compiling one unit, has no information about the use of 272 | variables, register allocation etc. occuring in other compilation 273 | units. Although in real life compilation units will probably be 274 | larger, the intention is that these effects of separate compilation 275 | are modeled in Dhrystone. 276 | 277 | A few language systems have post-linkage optimization available 278 | (e.g., final register allocation is performed after linkage). This 279 | is a borderline case: Post-linkage optimization involves additional 280 | program preparation time (although not as much as compilation in one 281 | unit) which may prevent its general use in practical programming. I 282 | think that since it defeats the intentions given above, it should not 283 | be used for Dhrystone. 284 | 285 | Unfortunately, ISO/ANSI Pascal does not contain language features for 286 | separate compilation. Although most commercial Pascal compilers 287 | provide separate compilation in some way, we cannot use it for 288 | Dhrystone since such a version would not be portable. Therefore, no 289 | attempt has been made to provide a Pascal version with several 290 | compilation units. 291 | 292 | o No procedure merging 293 | 294 | Although Dhrystone contains some very short procedures where 295 | execution would benefit from procedure merging (inlining, macro 296 | expansion of procedures), procedure merging is not to be used. The 297 | reason is that the percentage of procedure and function calls is part 298 | of the "Dhrystone distribution" of statements contained in [1]. 299 | 300 | o Other optimizations are allowed, but they should be indicated 301 | 302 | It is often hard to draw an exact line between "normal code 303 | generation" and "optimization" in compilers: Some compilers perform 304 | operations by default that are invoked in other compilers only when 305 | optimization is explicitly requested. Also, we cannot avoid that in 306 | benchmarking people try to achieve results that look as good as 307 | possible. Therefore, optimizations performed by compilers - other 308 | than those listed above - are not forbidden when Dhrystone execution 309 | times are measured. Dhrystone is not intended to be non-optimizable 310 | but is intended to be similarly optimizable as normal programs. For 311 | example, there are several places in Dhrystone where performance 312 | benefits from optimizations like Common Subexpression Elimination, 313 | Value Propagation etc., but normal programs usually also benefit from 314 | these optimizations. Therefore, no effort was made to artificially 315 | prevent such optimizations. However, measurement reports should 316 | indicate which compiler optimization levels have been used, and 317 | reporting results with different levels of compiler optimization for 318 | the same hardware is encouraged. 319 | 320 | o Default results are those without "register" declarations (C version) 321 | 322 | When Dhrystone results are quoted without additional qualification, 323 | they should be understood as results obtained without use of the 324 | "register" attribute. Good compilers should be able to make good use 325 | of registers even without explicit register declarations ([3], p. 326 | 193). 327 | 328 | Of course, for experimental purposes, post-linkage optimization, 329 | procedure merging and/or compilation in one unit can be done to 330 | determine their effects. However, Dhrystone numbers obtained under 331 | these conditions should be explicitly marked as such; "normal" 332 | Dhrystone results should be understood as results obtained following 333 | the ground rules listed above. 334 | 335 | In any case, for serious performance evaluation, users are advised to 336 | ask for code listings and to check them carefully. In this way, when 337 | results for different systems are compared, the reader can get a 338 | feeling how much performance difference is due to compiler optimization 339 | and how much is due to hardware speed. 340 | 341 | 342 | 6. Acknowledgements 343 | 344 | The C version 2.0 of Dhrystone has been developed in cooperation with 345 | Rick Richardson (Tinton Falls, NJ), it incorporates many ideas from the 346 | "Version 1.1" distributed previously by him over the UNIX network 347 | Usenet. Through his activity with Usenet, Rick Richardson has made a 348 | very valuable contribution to the dissemination of the benchmark. I 349 | also thank Chaim Benedelac (National Semiconductor), David Ditzel 350 | (SUN), Earl Killian and John Mashey (MIPS), Alan Smith and Rafael 351 | Saavedra-Barrera (UC at Berkeley) for their help with comments on 352 | earlier versions of the benchmark. 353 | 354 | 355 | 7. Bibliography 356 | 357 | [1] 358 | Reinhold P. Weicker: Dhrystone: A Synthetic Systems Programming 359 | Benchmark. 360 | Communications of the ACM 27, 10 (Oct. 1984), 1013-1030 361 | 362 | [2] 363 | Rick Richardson: Dhrystone 1.1 Benchmark Summary (and Program Text) 364 | Informal Distribution via "Usenet", Last Version Known to me: Sept. 365 | 21, 1987 366 | 367 | [3] 368 | Brian W. Kernighan and Dennis M. Ritchie: The C Programming 369 | Language. 370 | Prentice-Hall, Englewood Cliffs (NJ) 1978 371 | 372 | -------------------------------------------------------------------------------- /v2.0/dhry_global.h: -------------------------------------------------------------------------------- 1 | /* 2 | **************************************************************************** 3 | * 4 | * "DHRYSTONE" Benchmark Program 5 | * ----------------------------- 6 | * 7 | * Version: C, Version 2.0 8 | * 9 | * File: dhry_global.h (part 1 of 3) 10 | * 11 | * Date: March 3, 1988 12 | * 13 | * Author: Reinhold P. Weicker 14 | * Siemens AG, E STE 35 15 | * Postfach 3240 16 | * 8520 Erlangen 17 | * Germany (West) 18 | * Phone: [xxx-49]-9131-7-20330 19 | * (8-17 Central European Time) 20 | * Usenet: ..!mcvax!unido!estevax!weicker 21 | * 22 | * Original Version (in Ada) published in 23 | * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), 24 | * pp. 1013 - 1030, together with the statistics 25 | * on which the distribution of statements etc. is based. 26 | * 27 | * In this C version, the following C library functions are used: 28 | * - strcpy, strcmp (inside the measurement loop) 29 | * - printf, scanf (outside the measurement loop) 30 | * In addition, UNIX system calls "times ()" or "time ()" 31 | * are used for execution time measurement. For measurements 32 | * on other systems, these calls have to be changed. 33 | * 34 | * Collection of Results: 35 | * Reinhold Weicker (address see above) and 36 | * 37 | * Rick Richardson 38 | * PC Research. Inc. 39 | * 94 Apple Orchard Drive 40 | * Tinton Falls, NJ 07724 41 | * Phone: (201) 834-1378 (9-17 EST) 42 | * Usenet: ...!seismo!uunet!pcrat!rick 43 | * 44 | * Please send results to Reinhold Weicker and/or Rick Richardson. 45 | * Complete information should be given on hardware and software used. 46 | * Hardware information includes: Machine type, CPU, type and size 47 | * of caches; for microprocessors: clock frequency, memory speed 48 | * (number of wait states). 49 | * Software information includes: Compiler (and runtime library) 50 | * manufacturer and version, compilation switches, OS version. 51 | * The Operating System version may give an indication about the 52 | * compiler; Dhrystone itself performs no OS calls in the measurement loop. 53 | * 54 | * The complete output generated by the program should be mailed 55 | * such that at least some checks for correctness can be made. 56 | * 57 | *************************************************************************** 58 | * 59 | * History: This version C/2.0 has been made for two reasons: 60 | * 61 | * 1) There is an obvious need for a common C version of 62 | * Dhrystone, since C is at present the most popular system 63 | * programming language for the class of processors 64 | * (microcomputers, minicomputers) where Dhrystone is used most. 65 | * There should be, as far as possible, only one C version of 66 | * Dhrystone such that results can be compared without 67 | * restrictions. In the past, the C versions distributed 68 | * by Rick Richardson (Version 1.1) and by Reinhold Weicker 69 | * had small (though not significant) differences. 70 | * 71 | * 2) As far as it is possible without changes to the Dhrystone 72 | * statistics, optimizing compilers should be prevented from 73 | * removing significant statements. 74 | * 75 | * This C version has been developed in cooperation with 76 | * Rick Richardson (Tinton Falls, NJ), it incorporates many 77 | * ideas from the "Version 1.1" distributed previously by 78 | * him over the UNIX network Usenet. 79 | * I also thank Chaim Benedelac (National Semiconductor), 80 | * David Ditzel (SUN), Earl Killian and John Mashey (MIPS), 81 | * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) 82 | * for their help with comments on earlier versions of the 83 | * benchmark. 84 | * 85 | * Changes: In the initialization part, this version follows mostly 86 | * Rick Richardson's version distributed via Usenet, not the 87 | * version distributed earlier via floppy disk by Reinhold Weicker. 88 | * As a concession to older compilers, names have been made 89 | * unique within the first 8 characters. 90 | * Inside the measurement loop, this version follows the 91 | * version previously distributed by Reinhold Weicker. 92 | * 93 | * At several places in the benchmark, code has been added, 94 | * but within the measurement loop only in branches that 95 | * are not executed. The intention is that optimizing compilers 96 | * should be prevented from moving code out of the measurement 97 | * loop, or from removing code altogether. Since the statements 98 | * that are executed within the measurement loop have NOT been 99 | * changed, the numbers defining the "Dhrystone distribution" 100 | * (distribution of statements, operand types and locality) 101 | * still hold. Except for sophisticated optimizing compilers, 102 | * execution times for this version should be the same as 103 | * for previous versions. 104 | * 105 | * Since it has proven difficult to subtract the time for the 106 | * measurement loop overhead in a correct way, the loop check 107 | * has been made a part of the benchmark. This does have 108 | * an impact - though a very minor one - on the distribution 109 | * statistics which have been updated for this version. 110 | * 111 | * All changes within the measurement loop are described 112 | * and discussed in the companion paper "Rationale for 113 | * Dhrystone version 2". 114 | * 115 | * Because of the self-imposed limitation that the order and 116 | * distribution of the executed statements should not be 117 | * changed, there are still cases where optimizing compilers 118 | * may not generate code for some statements. To a certain 119 | * degree, this is unavoidable for small synthetic benchmarks. 120 | * Users of the benchmark are advised to check code listings 121 | * whether code is generated for all statements of Dhrystone. 122 | * 123 | *************************************************************************** 124 | * 125 | * Defines: The following "Defines" are possible: 126 | * -DREG=register (default: Not defined) 127 | * As an approximation to what an average C programmer 128 | * might do, the "register" storage class is applied 129 | * (if enabled by -DREG=register) 130 | * - for local variables, if they are used (dynamically) 131 | * five or more times 132 | * - for parameters if they are used (dynamically) 133 | * six or more times 134 | * Note that an optimal "register" strategy is 135 | * compiler-dependent, and that "register" declarations 136 | * do not necessarily lead to faster execution. 137 | * -DNOSTRUCTASSIGN (default: Not defined) 138 | * Define if the C compiler does not support 139 | * assignment of structures. 140 | * -DNOENUMS (default: Not defined) 141 | * Define if the C compiler does not support 142 | * enumeration types. 143 | * -DTIMES (default) 144 | * -DTIME 145 | * The "times" function of UNIX (returning process times) 146 | * or the "time" function (returning wallclock time) 147 | * is used for measurement. 148 | * For single user machines, "time ()" is adequate. For 149 | * multi-user machines where you cannot get single-user 150 | * access, use the "times ()" function. If you have 151 | * neither, use a stopwatch in the dead of night. 152 | * "printf"s are provided marking the points "Start Timer" 153 | * and "Stop Timer". DO NOT use the UNIX "time(1)" 154 | * command, as this will measure the total time to 155 | * run this program, which will (erroneously) include 156 | * the time to allocate storage (malloc) and to perform 157 | * the initialization. 158 | * -DHZ=nnn (default: 60) 159 | * The function "times" returns process times in 160 | * 1/HZ seconds, with HZ = 60 for most systems. 161 | * CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY 162 | * THE DEFAULT VALUE. 163 | * 164 | *************************************************************************** 165 | * 166 | * Compilation model and measurement (IMPORTANT): 167 | * 168 | * This C version of Dhrystone consists of three files: 169 | * - dhry_global.h (this file, containing global definitions and comments) 170 | * - dhry_pack_1.c (containing the code corresponding to Ada package Pack_1) 171 | * - dhry_pack_2.c (containing the code corresponding to Ada package Pack_2) 172 | * 173 | * The following "ground rules" apply for measurements: 174 | * - Separate compilation 175 | * - No procedure merging 176 | * - Otherwise, compiler optimizations are allowed but should be indicated 177 | * - Default results are those without register declarations 178 | * See the companion paper "Rationale for Dhrystone Version 2" for a more 179 | * detailed discussion of these ground rules. 180 | * 181 | * For 16-Bit processors (e.g. 80186, 80286), times for all compilation 182 | * models ("small", "medium", "large" etc.) should be given if possible, 183 | * together with a definition of these models for the compiler system used. 184 | * 185 | ************************************************************************** 186 | * 187 | * Dhrystone (C version) statistics: 188 | * 189 | * [Comment from the first distribution, updated for version 2. 190 | * Note that because of language differences, the numbers are slightly 191 | * different from the Ada version.] 192 | * 193 | * The following program contains statements of a high level programming 194 | * language (here: C) in a distribution considered representative: 195 | * 196 | * assignments 52 (51.0 %) 197 | * control statements 33 (32.4 %) 198 | * procedure, function calls 17 (16.7 %) 199 | * 200 | * 103 statements are dynamically executed. The program is balanced with 201 | * respect to the three aspects: 202 | * 203 | * - statement type 204 | * - operand type 205 | * - operand locality 206 | * operand global, local, parameter, or constant. 207 | * 208 | * The combination of these three aspects is balanced only approximately. 209 | * 210 | * 1. Statement Type: 211 | * ----------------- number 212 | * 213 | * V1 = V2 9 214 | * (incl. V1 = F(..) 215 | * V = Constant 12 216 | * Assignment, 7 217 | * with array element 218 | * Assignment, 6 219 | * with record component 220 | * -- 221 | * 34 34 222 | * 223 | * X = Y +|-|"&&"|"|" Z 5 224 | * X = Y +|-|"==" Constant 6 225 | * X = X +|- 1 3 226 | * X = Y *|/ Z 2 227 | * X = Expression, 1 228 | * two operators 229 | * X = Expression, 1 230 | * three operators 231 | * -- 232 | * 18 18 233 | * 234 | * if .... 14 235 | * with "else" 7 236 | * without "else" 7 237 | * executed 3 238 | * not executed 4 239 | * for ... 7 | counted every time 240 | * while ... 4 | the loop condition 241 | * do ... while 1 | is evaluated 242 | * switch ... 1 243 | * break 1 244 | * declaration with 1 245 | * initialization 246 | * -- 247 | * 34 34 248 | * 249 | * P (...) procedure call 11 250 | * user procedure 10 251 | * library procedure 1 252 | * X = F (...) 253 | * function call 6 254 | * user function 5 255 | * library function 1 256 | * -- 257 | * 17 17 258 | * --- 259 | * 103 260 | * 261 | * The average number of parameters in procedure or function calls 262 | * is 1.82 (not counting the function values as implicit parameters). 263 | * 264 | * 265 | * 2. Operators 266 | * ------------ 267 | * number approximate 268 | * percentage 269 | * 270 | * Arithmetic 32 50.8 271 | * 272 | * + 21 33.3 273 | * - 7 11.1 274 | * * 3 4.8 275 | * / (int div) 1 1.6 276 | * 277 | * Comparison 27 42.8 278 | * 279 | * == 9 14.3 280 | * /= 4 6.3 281 | * > 1 1.6 282 | * < 3 4.8 283 | * >= 1 1.6 284 | * <= 9 14.3 285 | * 286 | * Logic 4 6.3 287 | * 288 | * && (AND-THEN) 1 1.6 289 | * | (OR) 1 1.6 290 | * ! (NOT) 2 3.2 291 | * 292 | * -- ----- 293 | * 63 100.1 294 | * 295 | * 296 | * 3. Operand Type (counted once per operand reference): 297 | * --------------- 298 | * number approximate 299 | * percentage 300 | * 301 | * Integer 175 72.3 % 302 | * Character 45 18.6 % 303 | * Pointer 12 5.0 % 304 | * String30 6 2.5 % 305 | * Array 2 0.8 % 306 | * Record 2 0.8 % 307 | * --- ------- 308 | * 242 100.0 % 309 | * 310 | * When there is an access path leading to the final operand (e.g. a record 311 | * component), only the final data type on the access path is counted. 312 | * 313 | * 314 | * 4. Operand Locality: 315 | * ------------------- 316 | * number approximate 317 | * percentage 318 | * 319 | * local variable 114 47.1 % 320 | * global variable 22 9.1 % 321 | * parameter 45 18.6 % 322 | * value 23 9.5 % 323 | * reference 22 9.1 % 324 | * function result 6 2.5 % 325 | * constant 55 22.7 % 326 | * --- ------- 327 | * 242 100.0 % 328 | * 329 | * 330 | * The program does not compute anything meaningful, but it is syntactically 331 | * and semantically correct. All variables have a value assigned to them 332 | * before they are used as a source operand. 333 | * 334 | * There has been no explicit effort to account for the effects of a 335 | * cache, or to balance the use of long or short displacements for code or 336 | * data. 337 | * 338 | *************************************************************************** 339 | */ 340 | 341 | /* Compiler and system dependent definitions: */ 342 | 343 | #ifndef TIME 344 | #ifndef TIMES 345 | #define TIMES 346 | #endif 347 | #endif 348 | /* Use "times" function for measurement */ 349 | /* unless explicitly defined otherwise */ 350 | #ifndef HZ 351 | #define HZ 60 352 | #endif 353 | /* Use HZ = 60 for "times" function */ 354 | /* unless explicitly defined otherwise */ 355 | 356 | #ifdef TIMES 357 | #include 358 | #include 359 | /* for "times" */ 360 | #endif 361 | 362 | #define Mic_secs_Per_Second 1000000.0 363 | /* UNIX C returns process times in seconds/HZ */ 364 | 365 | #ifdef NOSTRUCTASSIGN 366 | #define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) 367 | #else 368 | #define structassign(d, s) d = s 369 | #endif 370 | 371 | #ifdef NOENUM 372 | #define Ident_1 0 373 | #define Ident_2 1 374 | #define Ident_3 2 375 | #define Ident_4 3 376 | #define Ident_5 4 377 | typedef int Enumeration; 378 | #else 379 | typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5} 380 | Enumeration; 381 | #endif 382 | /* for boolean and enumeration types in Ada, Pascal */ 383 | 384 | /* General definitions: */ 385 | 386 | #include 387 | /* for strcpy, strcmp */ 388 | 389 | #define Null 0 390 | /* Value of a Null pointer */ 391 | #define true 1 392 | #define false 0 393 | 394 | typedef int One_Thirty; 395 | typedef int One_Fifty; 396 | typedef char Capital_Letter; 397 | typedef int Boolean; 398 | typedef char Str_30 [31]; 399 | typedef int Arr_1_Dim [50]; 400 | typedef int Arr_2_Dim [50] [50]; 401 | 402 | typedef struct record 403 | { 404 | struct record *Ptr_Comp; 405 | Enumeration Discr; 406 | union { 407 | struct { 408 | Enumeration Enum_Comp; 409 | int Int_Comp; 410 | char Str_Comp [31]; 411 | } var_1; 412 | struct { 413 | Enumeration E_Comp_2; 414 | char Str_2_Comp [31]; 415 | } var_2; 416 | struct { 417 | char Ch_1_Comp; 418 | char Ch_2_Comp; 419 | } var_3; 420 | } variant; 421 | } Rec_Type, *Rec_Pointer; 422 | 423 | 424 | -------------------------------------------------------------------------------- /v2.1/RATIONALE: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dhrystone Benchmark: Rationale for Version 2 and Measurement Rules 4 | 5 | 6 | Reinhold P. Weicker 7 | Siemens AG, E STE 35 8 | Postfach 3240 9 | D-8520 Erlangen 10 | Germany (West) 11 | 12 | 13 | 14 | 15 | 1. Why a Version 2 of Dhrystone? 16 | 17 | The Dhrystone benchmark program [1] has become a popular benchmark for 18 | CPU/compiler performance measurement, in particular in the area of 19 | minicomputers, workstations, PC's and microprocesors. It apparently satisfies 20 | a need for an easy-to-use integer benchmark; it gives a first performance 21 | indication which is more meaningful than MIPS numbers which, in their literal 22 | meaning (million instructions per second), cannot be used across different 23 | instruction sets (e.g. RISC vs. CISC). With the increasing use of the 24 | benchmark, it seems necessary to reconsider the benchmark and to check whether 25 | it can still fulfill this function. Version 2 of Dhrystone is the result of 26 | such a re-evaluation, it has been made for two reasons: 27 | 28 | o Dhrystone has been published in Ada [1], and Versions in Ada, Pascal and C 29 | have been distributed by Reinhold Weicker via floppy disk. However, the 30 | version that was used most often for benchmarking has been the version made 31 | by Rick Richardson by another translation from the Ada version into the C 32 | programming language, this has been the version distributed via the UNIX 33 | network Usenet [2]. 34 | 35 | There is an obvious need for a common C version of Dhrystone, since C is at 36 | present the most popular system programming language for the class of 37 | systems (microcomputers, minicomputers, workstations) where Dhrystone is 38 | used most. There should be, as far as possible, only one C version of 39 | Dhrystone such that results can be compared without restrictions. In the 40 | past, the C versions distributed by Rick Richardson (Version 1.1) and by 41 | Reinhold Weicker had small (though not significant) differences. 42 | 43 | Together with the new C version, the Ada and Pascal versions have been 44 | updated as well. 45 | 46 | o As far as it is possible without changes to the Dhrystone statistics, 47 | optimizing compilers should be prevented from removing significant 48 | statements. It has turned out in the past that optimizing compilers 49 | suppressed code generation for too many statements (by "dead code removal" 50 | or "dead variable elimination"). This has lead to the danger that 51 | benchmarking results obtained by a naive application of Dhrystone - without 52 | inspection of the code that was generated - could become meaningless. 53 | 54 | The overall policiy for version 2 has been that the distribution of 55 | statements, operand types and operand locality described in [1] should remain 56 | unchanged as much as possible. (Very few changes were necessary; their impact 57 | should be negligible.) Also, the order of statements should remain unchanged. 58 | Although I am aware of some critical remarks on the benchmark - I agree with 59 | several of them - and know some suggestions for improvement, I didn't want to 60 | change the benchmark into something different from what has become known as 61 | "Dhrystone"; the confusion generated by such a change would probably outweight 62 | the benefits. If I were to write a new benchmark program, I wouldn't give it 63 | the name "Dhrystone" since this denotes the program published in [1]. 64 | However, I do recognize the need for a larger number of representative 65 | programs that can be used as benchmarks; users should always be encouraged to 66 | use more than just one benchmark. 67 | 68 | The new versions (version 2.1 for C, Pascal and Ada) will be distributed as 69 | widely as possible. (Version 2.1 differs from version 2.0 distributed via the 70 | UNIX Network Usenet in March 1988 only in a few corrections for minor 71 | deficiencies found by users of version 2.0.) Readers who want to use the 72 | benchmark for their own measurements can obtain a copy in machine-readable 73 | form on floppy disk (MS-DOS or XENIX format) from the author. 74 | 75 | 76 | 2. Overall Characteristics of Version 2 77 | 78 | In general, version 2 follows - in the parts that are significant for 79 | performance measurement, i.e. within the measurement loop - the published 80 | (Ada) version and the C versions previously distributed. Where the versions 81 | distributed by Rick Richardson [2] and Reinhold Weicker have been different, 82 | it follows the version distributed by Reinhold Weicker. (However, the 83 | differences have been so small that their impact on execution time in all 84 | likelihood has been negligible.) The initialization and UNIX instrumentation 85 | part - which had been omitted in [1] - follows mostly the ideas of Rick 86 | Richardson [2]. However, any changes in the initialization part and in the 87 | printing of the result have no impact on performance measurement since they 88 | are outside the measaurement loop. As a concession to older compilers, names 89 | have been made unique within the first 8 characters for the C version. 90 | 91 | The original publication of Dhrystone did not contain any statements for time 92 | measurement since they are necessarily system-dependent. However, it turned 93 | out that it is not enough just to inclose the main procedure of Dhrystone in a 94 | loop and to measure the execution time. If the variables that are computed 95 | are not used somehow, there is the danger that the compiler considers them as 96 | "dead variables" and suppresses code generation for a part of the statements. 97 | Therefore in version 2 all variables of "main" are printed at the end of the 98 | program. This also permits some plausibility control for correct execution of 99 | the benchmark. 100 | 101 | At several places in the benchmark, code has been added, but only in branches 102 | that are not executed. The intention is that optimizing compilers should be 103 | prevented from moving code out of the measurement loop, or from removing code 104 | altogether. Statements that are executed have been changed in very few places 105 | only. In these cases, only the role of some operands has been changed, and it 106 | was made sure that the numbers defining the "Dhrystone distribution" 107 | (distribution of statements, operand types and locality) still hold as much as 108 | possible. Except for sophisticated optimizing compilers, execution times for 109 | version 2.1 should be the same as for previous versions. 110 | 111 | Because of the self-imposed limitation that the order and distribution of the 112 | executed statements should not be changed, there are still cases where 113 | optimizing compilers may not generate code for some statements. To a certain 114 | degree, this is unavoidable for small synthetic benchmarks. Users of the 115 | benchmark are advised to check code listings whether code is generated for all 116 | statements of Dhrystone. 117 | 118 | Contrary to the suggestion in the published paper and its realization in the 119 | versions previously distributed, no attempt has been made to subtract the time 120 | for the measurement loop overhead. (This calculation has proven difficult to 121 | implement in a correct way, and its omission makes the program simpler.) 122 | However, since the loop check is now part of the benchmark, this does have an 123 | impact - though a very minor one - on the distribution statistics which have 124 | been updated for this version. 125 | 126 | 127 | 3. Discussion of Individual Changes 128 | 129 | In this section, all changes are described that affect the measurement loop 130 | and that are not just renamings of variables. All remarks refer to the C 131 | version; the other language versions have been updated similarly. 132 | 133 | In addition to adding the measurement loop and the printout statements, 134 | changes have been made at the following places: 135 | 136 | o In procedure "main", three statements have been added in the non-executed 137 | "then" part of the statement 138 | 139 | if (Enum_Loc == Func_1 (Ch_Index, 'C')) 140 | 141 | they are 142 | 143 | strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); 144 | Int_2_Loc = Run_Index; 145 | Int_Glob = Run_Index; 146 | 147 | The string assignment prevents movement of the preceding assignment to 148 | Str_2_Loc (5'th statement of "main") out of the measurement loop (This 149 | probably will not happen for the C version, but it did happen with another 150 | language and compiler.) The assignment to Int_2_Loc prevents value 151 | propagation for Int_2_Loc, and the assignment to Int_Glob makes the value of 152 | Int_Glob possibly dependent from the value of Run_Index. 153 | 154 | o In the three arithmetic computations at the end of the measurement loop in 155 | "main ", the role of some variables has been exchanged, to prevent the 156 | division from just cancelling out the multiplication as it was in [1]. A 157 | very smart compiler might have recognized this and suppressed code 158 | generation for the division. 159 | 160 | o For Proc_2, no code has been changed, but the values of the actual parameter 161 | have changed due to changes in "main". 162 | 163 | o In Proc_4, the second assignment has been changed from 164 | 165 | Bool_Loc = Bool_Loc | Bool_Glob; 166 | 167 | to 168 | 169 | Bool_Glob = Bool_Loc | Bool_Glob; 170 | 171 | It now assigns a value to a global variable instead of a local variable 172 | (Bool_Loc); Bool_Loc would be a "dead variable" which is not used 173 | afterwards. 174 | 175 | o In Func_1, the statement 176 | 177 | Ch_1_Glob = Ch_1_Loc; 178 | 179 | was added in the non-executed "else" part of the "if" statement, to prevent 180 | the suppression of code generation for the assignment to Ch_1_Loc. 181 | 182 | o In Func_2, the second character comparison statement has been changed to 183 | 184 | if (Ch_Loc == 'R') 185 | 186 | ('R' instead of 'X') because a comparison with 'X' is implied in the 187 | preceding "if" statement. 188 | 189 | Also in Func_2, the statement 190 | 191 | Int_Glob = Int_Loc; 192 | 193 | has been added in the non-executed part of the last "if" statement, in order 194 | to prevent Int_Loc from becoming a dead variable. 195 | 196 | o In Func_3, a non-executed "else" part has been added to the "if" statement. 197 | While the program would not be incorrect without this "else" part, it is 198 | considered bad programming practice if a function can be left without a 199 | return value. 200 | 201 | To compensate for this change, the (non-executed) "else" part in the "if" 202 | statement of Proc_3 was removed. 203 | 204 | The distribution statistics have been changed only by the addition of the 205 | measurement loop iteration (1 additional statement, 4 additional local integer 206 | operands) and by the change in Proc_4 (one operand changed from local to 207 | global). The distribution statistics in the comment headers have been updated 208 | accordingly. 209 | 210 | 211 | 4. String Operations 212 | 213 | The string operations (string assignment and string comparison) have not been 214 | changed, to keep the program consistent with the original version. 215 | 216 | There has been some concern that the string operations are over-represented in 217 | the program, and that execution time is dominated by these operations. This 218 | was true in particular when optimizing compilers removed too much code in the 219 | main part of the program, this should have been mitigated in version 2. 220 | 221 | It should be noted that this is a language-dependent issue: Dhrystone was 222 | first published in Ada, and with Ada or Pascal semantics, the time spent in 223 | the string operations is, at least in all implementations known to me, 224 | considerably smaller. In Ada and Pascal, assignment and comparison of strings 225 | are operators defined in the language, and the upper bounds of the strings 226 | occuring in Dhrystone are part of the type information known at compilation 227 | time. The compilers can therefore generate efficient inline code. In C, 228 | string assignemt and comparisons are not part of the language, so the string 229 | operations must be expressed in terms of the C library functions "strcpy" and 230 | "strcmp". (ANSI C allows an implementation to use inline code for these 231 | functions.) In addition to the overhead caused by additional function calls, 232 | these functions are defined for null-terminated strings where the length of 233 | the strings is not known at compilation time; the function has to check every 234 | byte for the termination condition (the null byte). 235 | 236 | Obviously, a C library which includes efficiently coded "strcpy" and "strcmp" 237 | functions helps to obtain good Dhrystone results. However, I don't think that 238 | this is unfair since string functions do occur quite frequently in real 239 | programs (editors, command interpreters, etc.). If the strings functions are 240 | implemented efficiently, this helps real programs as well as benchmark 241 | programs. 242 | 243 | I admit that the string comparison in Dhrystone terminates later (after 244 | scanning 20 characters) than most string comparisons in real programs. For 245 | consistency with the original benchmark, I didn't change the program despite 246 | this weakness. 247 | 248 | 249 | 5. Intended Use of Dhrystone 250 | 251 | When Dhrystone is used, the following "ground rules" apply: 252 | 253 | o Separate compilation (Ada and C versions) 254 | 255 | As mentioned in [1], Dhrystone was written to reflect actual programming 256 | practice in systems programming. The division into several compilation 257 | units (5 in the Ada version, 2 in the C version) is intended, as is the 258 | distribution of inter-module and intra-module subprogram calls. Although on 259 | many systems there will be no difference in execution time to a Dhrystone 260 | version where all compilation units are merged into one file, the rule is 261 | that separate compilation should be used. The intention is that real 262 | programming practice, where programs consist of several independently 263 | compiled units, should be reflected. This also has implies that the 264 | compiler, while compiling one unit, has no information about the use of 265 | variables, register allocation etc. occuring in other compilation units. 266 | Although in real life compilation units will probably be larger, the 267 | intention is that these effects of separate compilation are modeled in 268 | Dhrystone. 269 | 270 | A few language systems have post-linkage optimization available (e.g., final 271 | register allocation is performed after linkage). This is a borderline case: 272 | Post-linkage optimization involves additional program preparation time 273 | (although not as much as compilation in one unit) which may prevent its 274 | general use in practical programming. I think that since it defeats the 275 | intentions given above, it should not be used for Dhrystone. 276 | 277 | Unfortunately, ISO/ANSI Pascal does not contain language features for 278 | separate compilation. Although most commercial Pascal compilers provide 279 | separate compilation in some way, we cannot use it for Dhrystone since such 280 | a version would not be portable. Therefore, no attempt has been made to 281 | provide a Pascal version with several compilation units. 282 | 283 | o No procedure merging 284 | 285 | Although Dhrystone contains some very short procedures where execution would 286 | benefit from procedure merging (inlining, macro expansion of procedures), 287 | procedure merging is not to be used. The reason is that the percentage of 288 | procedure and function calls is part of the "Dhrystone distribution" of 289 | statements contained in [1]. This restriction does not hold for the string 290 | functions of the C version since ANSI C allows an implementation to use 291 | inline code for these functions. 292 | 293 | o Other optimizations are allowed, but they should be indicated 294 | 295 | It is often hard to draw an exact line between "normal code generation" and 296 | "optimization" in compilers: Some compilers perform operations by default 297 | that are invoked in other compilers only when optimization is explicitly 298 | requested. Also, we cannot avoid that in benchmarking people try to achieve 299 | results that look as good as possible. Therefore, optimizations performed 300 | by compilers - other than those listed above - are not forbidden when 301 | Dhrystone execution times are measured. Dhrystone is not intended to be 302 | non-optimizable but is intended to be similarly optimizable as normal 303 | programs. For example, there are several places in Dhrystone where 304 | performance benefits from optimizations like common subexpression 305 | elimination, value propagation etc., but normal programs usually also 306 | benefit from these optimizations. Therefore, no effort was made to 307 | artificially prevent such optimizations. However, measurement reports 308 | should indicate which compiler optimization levels have been used, and 309 | reporting results with different levels of compiler optimization for the 310 | same hardware is encouraged. 311 | 312 | o Default results are those without "register" declarations (C version) 313 | 314 | When Dhrystone results are quoted without additional qualification, they 315 | should be understood as results obtained without use of the "register" 316 | attribute. Good compilers should be able to make good use of registers even 317 | without explicit register declarations ([3], p. 193). 318 | 319 | Of course, for experimental purposes, post-linkage optimization, procedure 320 | merging and/or compilation in one unit can be done to determine their effects. 321 | However, Dhrystone numbers obtained under these conditions should be 322 | explicitly marked as such; "normal" Dhrystone results should be understood as 323 | results obtained following the ground rules listed above. 324 | 325 | In any case, for serious performance evaluation, users are advised to ask for 326 | code listings and to check them carefully. In this way, when results for 327 | different systems are compared, the reader can get a feeling how much 328 | performance difference is due to compiler optimization and how much is due to 329 | hardware speed. 330 | 331 | 332 | 6. Acknowledgements 333 | 334 | The C version 2.1 of Dhrystone has been developed in cooperation with Rick 335 | Richardson (Tinton Falls, NJ), it incorporates many ideas from the "Version 336 | 1.1" distributed previously by him over the UNIX network Usenet. Through his 337 | activity with Usenet, Rick Richardson has made a very valuable contribution to 338 | the dissemination of the benchmark. I also thank Chaim Benedelac (National 339 | Semiconductor), David Ditzel (SUN), Earl Killian and John Mashey (MIPS), Alan 340 | Smith and Rafael Saavedra-Barrera (UC at Berkeley) for their help with 341 | comments on earlier versions of the benchmark. 342 | 343 | 344 | 7. Bibliography 345 | 346 | [1] 347 | Reinhold P. Weicker: Dhrystone: A Synthetic Systems Programming Benchmark. 348 | Communications of the ACM 27, 10 (Oct. 1984), 1013-1030 349 | 350 | [2] 351 | Rick Richardson: Dhrystone 1.1 Benchmark Summary (and Program Text) 352 | Informal Distribution via "Usenet", Last Version Known to me: Sept. 21, 353 | 1987 354 | 355 | [3] 356 | Brian W. Kernighan and Dennis M. Ritchie: The C Programming Language. 357 | Prentice-Hall, Englewood Cliffs (NJ) 1978 358 | 359 | --------------------------------------------------------------------------------