# to unbundle, sh this file (in an empty directory) echo RATIONALE 1>&2 sed >RATIONALE <<'//GO.SYSIN DD RATIONALE' 's/^-//' - - Dhrystone Benchmark (Pascal Version 2): Rationale and Measurement Rules - - - Reinhold P. Weicker - Siemens AG, AUT E 51 - Postfach 3220 - D-8520 Erlangen - Germany (West) - - - - -1. Why a Version 2 of Dhrystone? - -The Dhrystone benchmark program [1] has become a popular benchmark for -CPU/compiler performance measurement, in particular in the area of -minicomputers, workstations, PC's and microprocesors. It apparently satisfies -a need for an easy-to-use integer benchmark; it gives a first performance -indication which is more meaningful than MIPS numbers which, in their literal -meaning (million instructions per second), cannot be used across different -instruction sets (e.g. RISC vs. CISC). With the increasing use of the -benchmark, it seems necessary to reconsider the benchmark and to check whether -it can still fulfill this function. Version 2 of Dhrystone is the result of -such a re-evaluation, it has been made for two reasons: - -o Dhrystone has been published in Ada [1], and Versions in Ada, Pascal and C - have been distributed by Reinhold Weicker via floppy disk. However, the - version that was used most often for benchmarking has been the C version - made by Rick Richardson by another translation from the Ada version into the - C programming language, this has been the version widely distributed via the - UNIX network Usenet [2]. - - C seems at present to be the most popular language to characterize the - performance for the class of systems (microcomputers, minicomputers, - workstations) where Dhrystone is used most; however, there is also an - apparent need for a common Pascal version of Dhrystone that benchmarkers can - refer to. There should be, as far as possible, only one version of - Dhrystone per language such that results can be compared without - restrictions. In order to allow cross-language comparisons, the Ada, - Pascal, and C versions should be maintained together. - - Both this Pascal version and the C version 2.1 have been updated in - parallel; the Ada version will be updated similarly. - -o As far as it is possible without changes to the Dhrystone statistics, - optimizing compilers should be prevented from removing significant - statements. It has turned out in the past that optimizing compilers - suppressed code generation for too many statements (by "dead code removal" - or "dead variable elimination"). This has lead to the danger that - benchmarking results obtained by a naive application of Dhrystone - without - inspection of the code that was generated - could become meaningless. - -The overall policiy for version 2 has been that the distribution of -statements, operand types and operand locality described in [1] should remain -unchanged as much as possible. (Very few changes were necessary; their impact -should be negligible.) Also, the order of statements should remain unchanged. -Although I am aware of some critical remarks on the benchmark - I agree with -several of them - and know some suggestions for improvement, I didn't want to -change the benchmark into something different from what has become known as -"Dhrystone"; the confusion generated by such a change would probably outweight -the benefits. If I were to write a new benchmark program, I wouldn't give it -the name "Dhrystone" since this denotes the program published in [1]. -However, I do recognize the need for a larger number of representative -programs that can be used as benchmarks; users should always be encouraged to -use more than just one benchmark. - -The new versions (version 2.1 for C, Pascal and Ada) will be distributed as -widely as possible. (This Pascal version 2.1 differs from version 2.0 -distributed via the UNIX Network Usenet in March 1988 only in a few -corrections for minor deficiencies found by users of version 2.0.) Readers -who want to use the benchmark for their own measurements can obtain a copy in -machine-readable form on floppy disk (MS-DOS or XENIX format) from the author. - - -2. Overall Characteristics of Version 2 - -In general, version 2 follows - in the parts that are significant for -performance measurement, i.e. within the measurement loop - the published -(Ada) version and the Pascal and C versions previously distributed. The -initialization part - which had been omitted in [1] - follows mostly the ideas -of Rick Richardson [2]. However, any changes in the initialization part and -in the printing of the result have no impact on performance measurement since -they are outside the measaurement loop. As a concession to older compilers, -names have been made unique within the first 8 characters. - -The original publication of Dhrystone did not contain any statements for time -measurement since they are necessarily system-dependent. However, it turned -out that it is not enough just to inclose the main procedure of Dhrystone in a -loop and to measure the execution time. If the variables that are computed -are not used somehow, there is the danger that the compiler considers them as -"dead variables" and suppresses code generation for a part of the statements. -Therefore in version 2 all variables of "main" are printed at the end of the -program. This also permits some plausibility control for correct execution of -the benchmark. - -At several places in the benchmark, code has been added, but only in branches -that are not executed. The intention is that optimizing compilers should be -prevented from moving code out of the measurement loop, or from removing code -altogether. Statements that are executed have been changed in very few places -only. In these cases, only the role of some operands has been changed, and it -was made sure that the numbers defining the "Dhrystone distribution" -(distribution of statements, operand types and locality) still hold as much as -possible. Except for sophisticated optimizing compilers, execution times for -version 2.1 should be the same as for previous versions. - -Because of the self-imposed limitation that the order and distribution of the -executed statements should not be changed, there are still cases where -optimizing compilers may not generate code for some statements. To a certain -degree, this is unavoidable for small synthetic benchmarks. Users of the -benchmark are advised to check code listings whether code is generated for all -statements of Dhrystone. - -Contrary to the suggestion in the published paper and its realization in the -versions previously distributed, no attempt has been made to subtract the time -for the measurement loop overhead. (This calculation has proven difficult to -implement in a correct way, and its omission makes the program simpler.) -However, since the loop check is now part of the benchmark, this does have an -impact - though a very minor one - on the distribution statistics which have -been updated for this version. - - -3. Discussion of Individual Changes - -In this section, all changes are described that affect the measurement loop -and that are not just renamings of variables. All remarks refer to the Pascal -version; the other language versions have been updated similarly. - -In addition to adding the measurement loop and the printout statements, -changes have been made at the following places: - -o In the main progam, three statements have been added in the non-executed - "then" part of the statement - - if EnumGlob = Func1 (CharIndex, 'C') - - they are - - String2Glob := 'DHRYSTONE PROGRAM, 3''RD STRING'; - Int2Glob := RunIndex; - IntGlob := RunIndex; - - The string assignment prevents movement of the preceding assignment to - String2Glob (5'th statement of the measurement loop) out of the loop (This - happened once with another language and compiler.) The assignment to - Int2Glob prevents value propagation for Int2Glob, and the assignment to - IntGlob makes the value of IntGlob possibly dependent from the value of - RunIndex. - -o In the three arithmetic computations at the end of the measurement loop in - the main progam the role of some variables has been exchanged, to prevent - the division from just cancelling out the multiplication as it was in [1]. - A very smart compiler might have recognized this and suppressed code - generation for the division. - -o For Proc2, no code has been changed, but the values of the actual parameter - have changed due to changes in the main program. - -o In Proc4, the second assignment has been changed from - - BoolLoc := BoolLoc or BoolGlob; - - to - - BoolGlob := BoolLoc or BoolGlob; - - It now assigns a value to a global variable instead of a local variable - (BoolLoc); BoolLoc would be a "dead variable" which is not used afterwards. - -o In Func1, the statement - - Char1Glob := Char1Loc; - - was added in the non-executed "else" part of the "if" statement, to prevent - the suppression of code generation for the assignment to Char1Loc. - -o In Func2, the second character comparison statement has been changed to - - if CharLoc = 'R' - - ('R' instead of 'X') because a comparison with 'X' is implied in the - preceding "if" statement. - - Also in Func2, the statement - - IntGlob := IntLoc; - - has been added in the non-executed part of the last "if" statement, in order - to prevent IntLoc from becoming a dead variable. - -o In Func3, a non-executed "else" part has been added to the "if" statement. - While the program would not be incorrect without this "else" part, it is - considered bad programming practice if a function can be left without a - return value. - - To compensate for this change, the (non-executed) "else" part in the "if" - statement of Proc3 was removed. - -The distribution statistics have been changed only by the addition of the -measurement loop iteration (1 additional statement, 4 additional global -integer operands) and by the change in Proc4 (one operand changed from local -to global). The distribution statistics in the comment headers have been -updated accordingly. - - -4. String Operations - -The string operations (string assignment and string comparison) have not been -changed, to keep the program consistent with the original version. - -For the C version, there has been some concern that the string operations are -over-represented in the program, and that execution time is dominated by these -operations. This was true in particular when optimizing compilers removed too -much code in the main part of the program, this should have been mitigated in -version 2. - -It should be noted that this is a language-dependent issue: Dhrystone was -first published in Ada, and with Ada or Pascal semantics, the time spent in -the string operations is, at least in all implementations known to me, -considerably smaller than in C. In Pascal and Ada, assignment and comparison -of strings are operators defined in the language, and the upper bounds of the -strings occuring in Dhrystone are part of the type information known at -compilation time. The compilers can therefore generate efficient inline code -whereas in C, the string operations must be expressed in terms of the C -library functions "strcpy" and "strcmp". (This is probably the main reason -why on most systems known to me, the Pascal version is faster than the C -version.) - -I admit that the string comparison in Dhrystone terminates later (after -scanning 20 characters) than most string comparisons in real programs. For -consistency with the original benchmark, I didn't change the program despite -this weakness. - - -5. Intended Use of Dhrystone - -When Dhrystone is used, the following "ground rules" apply: - -o No procedure merging - - Although Dhrystone contains some very short procedures where execution would - benefit from procedure merging (inlining, macro expansion of procedures), - procedure merging is not to be used. The reason is that the percentage of - procedure and function calls is part of the "Dhrystone distribution" of - statements contained in [1]. - - Of course, for experimental purposes, procedure merging can be done to - determine its effects. However, Dhrystone numbers obtained under these - conditions should be explicitly marked as such; "normal" Dhrystone results - should be understood as results obtained without procedure merging. - -o Other optimizations are allowed, but they should be indicated - - It is often hard to draw an exact line between "normal code generation" and - "optimization" in compilers: Some compilers perform operations by default - that are invoked in other compilers only when optimization is explicitly - requested. Also, we cannot avoid that in benchmarking people try to achieve - results that look as good as possible. Therefore, optimizations performed - by compilers - other than those listed above - are not forbidden when - Dhrystone execution times are measured. Dhrystone is not intended to be - non-optimizable but is intended to be similarly optimizable as normal - programs. For example, there are several places in Dhrystone where - performance benefits from optimizations like common subexpression - elimination, value propagation etc., but normal programs usually also - benefit from these optimizations. Therefore, no effort was made to - artificially prevent such optimizations. However, measurement reports - should indicate which compiler optimization levels have been used, and - reporting results with different levels of compiler optimization for the - same hardware is encouraged. - -o Separate compilation (Ada and C versions) - - As mentioned in [1], Dhrystone was written to reflect actual programming - practice in systems programming. The division of the Ada and C versions - into several compilation units (5 in the Ada version, 2 in the C version) is - intended, as is the distribution of inter-module and intra-module subprogram - calls. Although in real life compilation units will probably be larger, the - intention is that these effects of separate compilation are modeled in - Dhrystone. - - Unfortunately, ISO/ANSI Pascal does not contain language features for - separate compilation, and the standardization process for an extended Pascal - has not yet stabilized enough. Although most commercial Pascal compilers - provide separate compilation in some way, we cannot use it for Dhrystone - since such a version would not be portable. Therefore, no attempt has been - made to provide a Pascal version with several compilation units. Note that - for cross-language comparisons, this may give the Pascal version a - significant advantage over the Ada and C versions: A good Pascal compiler - can optimize over the whole program whereas an Ada or C compiler can only - optimize over one compilation unit. - -o Measurements with and without runtime checks are encouraged (Pascal and Ada - versions) - - Most Pascal systems provide the user with the option to insert runtime - checks into the generated code, usually by means of some pseudo-comment like - "{$C+}". Such runtime checks can be generated to check for - - o array indexes that are out of bounds, - o violation of range constraints for subrange types, - o incorrect use of variant record fields, - o non-initialized pointers, - o non-initialized variables in general. - - For the purpose of benchmarking, such runtime checks are usually suppressed. - This is necessary if Pascal results are to be compared with C results since - in C runtime checks are not possible or at least not done normally. - Therefore, results without additional remarks are understood as results - obtained without runtime checks. - - However, additional measurements with runtime checks enabled should be - performed wherever possible. Dhrystone intentionally contains statements - where additional code has to be generated for runtime checks as well as - other statements where a good compiler can recognize at compile time that - such checks are not necessary. The ratio of execution time with and without - runtime checks can indicate how much thought the implementors have given to - the idea [3] that runtime checks should be implemented so efficiently that - users are encouraged not to remove them for production runs. - - Different from Ada, Pascal does not define runtime checks as part of the - language. Therefore, if results with runtime checks are compared for - different syatems, users have to make sure that the same checks are - performed on both systems; otherwise the numbers are not comparable. - -In any case, for serious performance evaluation, users are advised to ask for -code listings and to check them carefully. In this way, when results for -different systems are compared, the reader can get a feeling how much -performance difference is due to compiler optimization and how much is due to -hardware speed. - - -6. Acknowledgements - -This Pascal version 2.1 of Dhrystone folllows closely the C version 2.1. This -C version has been developed in cooperation with Rick Richardson (Tinton -Falls, NJ), it incorporates many ideas from the "Version 1.1" distributed -previously by him over the UNIX network Usenet. Through his activity with -Usenet, Rick Richardson has made a very valuable contribution to the -dissemination of the benchmark. I also thank Chaim Benedelac (National -Semiconductor), David Ditzel (SUN), Earl Killian and John Mashey (MIPS), Alan -Smith and Rafael Saavedra-Barrera (UC at Berkeley) for their help with -comments on earlier versions of the benchmark. - - -7. Bibliography - -[1] - Reinhold P. Weicker: Dhrystone: A Synthetic Systems Programming Benchmark. - Communications of the ACM 27, 10 (Oct. 1984), 1013-1030 - -[2] - Rick Richardson: Dhrystone 1.1 Benchmark Summary (and Program Text) - Informal Distribution via "Usenet", Last Version Known to me: Sept. 21, - 1987 - -[3] - Ben Brosgol: Constraint Check Elimination - Ada Letters II-4 (Jan 1983), 54-57 - //GO.SYSIN DD RATIONALE echo README_P 1>&2 sed >README_P <<'//GO.SYSIN DD README_P' 's/^-//' -This "shar" file contains the documentation for the -electronic mail distribution of the Dhrystone benchmark (Pascal version 2.1); -a companion "shar" file contains the source code. -(Because of mail length restrictions for some mailers, I have -split the distribution in two parts.) - -For versions in other languages, see the other "shar" files. - -File containing the Pascal version: - - dhry.p - -The file RATIONALE contains a slightly modified version of the article - - "Dhrystone Benchmark: Rationale for Version 2 and Measurement Rules" - -which has been published, together with the C source code (Version 2.0), -in SIGPLAN Notices vol. 23, no. 8 (Aug. 1988), pp. 49-62. -This article explains all changes that have been made for Version 2, -compared with the version of the original publication -in Communications of the ACM vol. 27, no. 10 (Oct. 1984), pp. 1013-1030. -It also contains "ground rules" for benchmarking with Dhrystone -which should be followed by everyone who uses the program and publishes -Dhrystone results. - -Compared with the Version 2.0 published in SIGPLAN Notices, Version 2.1 -contains a few corrections that have been made after Version 2.0 was -distriobuted over the UNIX network Usenet. These small differences between -Version 2.0 and 2.1 should not affect execution time measurements. -For those who want to compare the exact contents of both versions, -the file "dhry_c.dif" contains the differences between the two versions (in C), -as generated by a file comparison of the corresponding files with the -UNIX utility "diff". - - -The following files are contained in other "shar" files: - -Files containing the C version (*.h: Header File, *.c: C Modules) - - dhry.h - dhry_1.c - dhry_2.c - -Files containing the Ada version (*.s: Specifications, *.b: Bodies): - - d_global.s - d_main.b - d_pack_1.b - d_pack_1.s - d_pack_2.b - d_pack_2.s - - -Recipients of this file who perform measurements are asked -to send measurement results to the author and/or to Rick Richardson. -Rick Richardson publishes regularly Dhrystone results on the UNIX network -Usenet. For submissions of results to him (preferably by electronic mail, -see address in the program header), he has provided a form which is contained -in the file "submit.frm". - -February 22, 1990 - - Reinhold P. Weicker - Siemens AG, AUT E 51 - Postfach 3220 - D-8520 Erlangen - Germany (West) - - Phone: [+49]-9131-7-20330 (8-17 Central European Time) - UUCP: ..!mcsun!unido!estevax!weicker //GO.SYSIN DD README_P echo dhry.p-1 1>&2 sed >dhry.p-1 <<'//GO.SYSIN DD dhry.p-1' 's/^-//' -(* - **************************************************************************** - * - * "DHRYSTONE" Benchmark Program - * ----------------------------- - * - * Version: Pascal, Version 2.1 - * - * File: dhry.p - * - * Date: May 25, 1988 - * - * Author: Reinhold P. Weicker - * Siemens AG, AUT E 51 - * Postfach 3220 - * 8520 Erlangen - * Germany (West) - * Phone: [+49]-9131-7-20330 - * (8-17 Central European Time) - * Usenet: ..!mcsun!unido!estevax!weicker - * - * Original Version (in Ada) published in - * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984), - * pp. 1013 - 1030, together with the statistics - * on which the distribution of statements etc. is based, - * - * This version uses calls to the Pascal runtime library of the - * Berkeley UNIX system (4.3 bsd) for time measurement. - * For measurements on other systems, these calls need to be - * modified. - * - * Collection of Results: - * Reinhold Weicker (address see above) and - * - * Rick Richardson - * PC Research. Inc. - * 94 Apple Orchard Drive - * Tinton Falls, NJ 07724 - * Phone: (201) 389-8963 (9-17 EST) - * Usenet: ...!uunet!pcrat!rick - * - * Please send results to Rick Richardson and/or Reinhold Weicker. - * Complete information should be given on hardware and software used. - * Hardware information includes: Machine type, CPU, type and size - * of caches; for microprocessors: clock frequency, memory speed - * (number of wait states). - * Software information includes: Compiler (and runtime library) - * manufacturer and version, compilation switches, OS version. - * The Operating System version may give an indication about the - * compiler; Dhrystone itself performs no OS calls in the measurement loop. - * - * The complete output generated by the program should be mailed - * such that at least some checks for correctness can be made. - * - **************************************************************************** - * - * History: This version Pascal/2.1 has been made for two reasons: - * - * 1) There is a need for a common Pascal version of - * Dhrystone. Although translation from the published (Ada) - * version to Pascal is straightforward in most aspects, - * there are cases where it may not be obvious to everyone. - * There should be, as far as possible, only one Pascal version - * of Dhrystone such that results can be compared without - * restrictions. Also, a Pascal version of Dhrystone has not yet - * found a network distribution comparable to the C version - * (version 1.1) distributed by Rick Richardson. - * - * 2) As far as it is possible without changes to the Dhrystone - * statistics, optimizing compilers should be prevented from - * removing significant statements. - * - * This Pascal version 2.1 has been made consistent with the - * C version 2.1; therefore the acknowledgments for the C version - * are due for the Pascal version as well: I thank - * Rick Richardson (Tinton Falls, NJ), Chaim Benedelac (Nat. - * Semi.), David Ditzel (SUN), Earl Killian and John Mashey (MIPS), - * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley) - * for their help with comments on earlier versions of the - * benchmark. - * - * Changes: In the initialization part, this version differs - * from the Pascal version previously distributed by Reinhold - * Weicker, the number of runs through Dhrystone is obtained - * interactively from the terminal. Output of the result - * has been changed to conform to the C version (2.1). - * The changes in the initialization part and in the printing - * of the result have no impact on performance measurement - * since they are outside the measaurement loop. - * - * Inside the measurement loop, this version follows the - * version previously distributed by Reinhold Weicker. - * As a correction to the published version, a statement - * initializing Array2Glob [8,7] (outside the measurement - * loop) has been added. Otherwise, this array element would - * have an undefined value. - * - * At several places in the benchmark, code has been added, - * but within the measurement loop only in branches that - * are not executed. The intention is that optimizing compilers - * should be prevented from moving code out of the measurement - * loop, or from removing code altogether. Since the statements - * that are executed within the measurement loop have NOT been - * changed, all numbers defining the "Dhrystone distribution" - * (distribution of statements, operand types and locality) - * still hold. Except for sophisticated optimizing compilers, - * execution times for this version should be the same as - * for previous versions. - * - * Since it has proven difficult to subtract the time for the - * measurement loop overhead in a correct way, the loop check - * has been made a part of the benchmark. This does have - * an impact - though a very minor one - on the distribution - * statistics which have been updated for this version. - * - * All changes within the measurement loop are described - * and discussed in the companion paper "Rationale for - * Dhrystone version 2". - * - * Because of the self-imposed limitation that the order and - * distribution of the executed statements should not be - * changed, there are still cases where optimizing compilers - * may not generate code for some statements. To a certain - * degree, this is unavoidable for small synthetic benchmarks. - * Users of the benchmark are advised to check code listings - * whether code is generated for all statements of Dhrystone. - * - * Version 2.1 is identical to version 2.0 distributed via - * the UNIX network Usenet in March 1988 except that it corrects - * some minor deficiencies that were found by users of version 2.0. - * The only change within the measurement loop is that a - * non-executed "else" part was added to the "if" statement in - * Func3, and a non-executed "else" part removed from Proc3. - * - *************************************************************************** - * - * Compilation model and measurement (IMPORTANT): - * - * This program contains the Dhrystone program, including measurement setup, - * in one file. The original (Ada) program contained three packages, - * - a package with global type definitions, - * - Pack_1, containing the main program (Proc_0 in Ada) and procedures - * Proc_1, ... , Proc_5, - * - Pack_2, containing Proc_6, ... , Proc_8, Func_1, ..., Func_3. - * Since ISO/ANSI Standard Pascal provides no means to express separate - * compilation (although many Pascal implementations provide such a feature), - * it is not possible to formulate a portable Pascal version with the program - * in several modules, corresponding more closely to the Ada and C versions. - * Therefore, no attempt has been made to construct a Pascal version with - * the program consisting of several modules. - * - * This difference may impact execution time because the compiler can - * perform more data flow analysis for a single-module program; - * sophisticated compilers may be able to suppress code generation for - * some parts of the program. - * Users should check machine code listings generated by the compiler - * to ensure that code is generated for all parts of the program. - * - * The following "ground rules" apply for measurements: - * - No procedure merging - * - Otherwise, compiler optimizations are allowed but should be indicated - * See the companion paper "Rationale for Dhrystone Version 2" for a more - * detailed discussion of these ground rules. - * - * For 16-Bit processors (e.g. 80x86), times for all compilation models - * ("small", "medium", "large") should be given if possible, together - * with a definition of these models for the compiler system used. - * - ************************************************************************** - * - * Dhrystone (Pascal version) statistics: - * - * [Comment from the first distribution by Reinhold Weicker, - * the distribution statistics have been updated for Version 2.1. - * Note that because of language differences, the numbers are different - * from the Ada version. The main difference is that the variables that - * are local variables of "Proc_0" (Ada) or "main" (C) are global - * variables in the Pascal version.] - * - * The following program contains statements of a high level programming - * language (here: Pascal) in a distribution considered representative: - * - * assignments 58 - * control statements 28 - * procedure, function calls 15 - * - * 100 statements are dynamically executed. The program is balanced with - * respect to the three aspects: - * - * - statement type - * - operand type (for simple data types) - * - operand access - * operand global, local, parameter, or constant. - * There is no static nesting of blocks or procedures, - * therefore all variables are either global or local. - * - * The combination of these three aspects is balanced only approximately. - * - * 1. Statement Type: - * ----------------- number - * - * V1 := V2 15 - * V := Constant 12 - * (incl. V1 := F(..) - * Assignment, 7 - * with array element - * Assignment, 6 - * with record component - * -- - * 40 40 - * - * X := Y +|-|and|or Z 5 - * X := Y +|-|"=" Constant 6 - * X := X +|- 1 3 - * X := Y *|/ Z 2 - * X := Expression, 1 - * two operators - * X := Expression, 1 - * three operators - * -- - * 18 18 - * - * if .... then .... 14 - * with "else" 7 - * without "else" 7 - * executed 3 - * not executed 4 - * for I in 1..N do ... 7 | counted every time - * while ... do ... 4 | the loop condition - * repeat ... until 1 | is evaluated - * case ... end 1 - * with 1 - * -- - * 28 28 - * - * P (...) procedure call 10 - * X := F (...) - * function call 5 - * -- - * 15 15 - * --- - * 101 - * - * 22 of the 58 assignments have a variable of a constrained - * (sub-)type as their destination. In general, discriminant checks - * will be necessary in these cases; however, the compiler may - * optimize out some of these checks. - * - * The average number of parameters in procedure or function calls - * is 1.80 (not counting the function values as implicit parameters). - * - * - * 2. Operators - * ------------ - * number approximate - * percentage - * - * Arithmetic 27 52.9 - * - * + 16 31.4 - * - 7 13.7 - * * 3 5.9 - * div 1 2.0 - * - * Comparison 20 39.2 - * - * = 9 17.6 - * <> 4 7.8 - * > 1 2.0 - * < 3 5.9 - * >= 1 2.0 - * <= 2 3.9 - * - * Logic 4 7.8 - * - * AND 1 2.0 - * OR 1 2.0 - * NOT 2 3.9 - * - * -- ----- - * 51 99.9 - * - * - * 3. Operand Type (counted once per operand reference): - * --------------- - * number approximate - * percentage - * - * Integer 135 54.7 % - * Character 47 19.0 % - * Enumeration 31 12.6 % - * Boolean 13 5.3 % - * Pointer 11 4.5 % - * String30 6 2.4 % - * Array 2 0.8 % - * Record 2 0.8 % - * --- ------- - * 247 100.1 % - * - * When there is an access path leading to the final operand (e.g. a record - * component), only the final data type on the access path is counted. - * - * There are 16 accesses to components of a record, 9 of them go to - * a component in a variant part. For some of these accesses, the - * compiler may suppress generation of code checking the tag field - * during optimization. - * - * - * 3. Operand Locality: - * ------------------- - * - * local variable 84 34.0 % - * global variable 58 23.5 % - * parameter 45 18.2 % - * value 23 9.3 % - * reference 22 8.9 % - * function result 5 2.0 % - * constant 55 22.3 % - * --- ------- - * 247 100.0 % - * - * - * The program does not compute anything meaningful, but it is syntactically - * and semantically correct. All variables have a value assigned to them - * before they are used as a source operand. - * - * There may be cases where a highly optimizing compiler may recognize - * unnecessary statements and may not generate code for them. - * - * There has been no explicit effort to account for the effects of a - * cache, or to balance the use of long or short displacements for code or - * data. - * - **************************************************************************** - *) - -(* - ************************************************ - * File split for transmission by electronic mail, - * attach the program (file dhry.p-2) here - ************************************************ - *) - //GO.SYSIN DD dhry.p-1 echo dhry.p-2 1>&2 sed >dhry.p-2 <<'//GO.SYSIN DD dhry.p-2' 's/^-//' - -program Dhrystone (input, output); -(***************) - -const (* for measurement *) - - MicrosecondsPerClock = 1000; - ClocksPerSecond = 1000; - (* In Berkeley UNIX Pascal, the function "clock" *) - (* returns milliseconds *) - TooSmallTime = 2000; - (* Measurements should last at least 2 seconds *) - -type - - (* Global type definitions *) - - Enumeration = (Ident1, Ident2, Ident3, Ident4, Ident5); - - OneToThirty = 1..30; - OneToFifty = 1..50; - CapitalLetter = 'A'..'Z'; - - String30 = packed array [OneToThirty] of char; - - Array1DimInteger = array [OneToFifty] of integer; - Array2DimInteger = array [OneToFifty, OneToFifty] of integer; - - RecordPointer = ^RecordType; - - RecordType = - record - PointerComp: RecordPointer; - case Discr: Enumeration of - Ident1: (* only this variant is used, *) - (* but in some cases discriminant *) - (* checks are necessary *) - (EnumComp: Enumeration; - IntComp: OneToFifty; - StringComp: String30); - Ident2: - (Enum2Comp: Enumeration; - String2Comp: String30); - Ident3, Ident4, Ident5: - (Char1Comp, - Char2Comp: char); - end; (* record *) - -var - - (* Ada version: Variables local in Proc_0 *) - - Int1Glob, - Int2Glob, - Int3Glob: OneToFifty; - CharIndex: char; - EnumGlob: Enumeration; - String1Glob, - String2Glob: String30; - - (* Ada version: Variables global in Pack_1 *) - - PointerGlob, - NextPointerGlob: RecordPointer; - IntGlob: integer; - - BoolGlob: boolean; - Char1Glob, - Char2Glob: char; - Array1Glob: Array1DimInteger; - Array2Glob: Array2DimInteger; - - (* Variables for measurement *) - - RunIndex, - NumberOfRuns, - BeginClock, - EndClock, - SumClocks: integer; - Microseconds, - DhrystonesPerSecond: real; - I: integer; - - (* end of variables for measurement *) - -procedure Proc1 ( PointerParVal: RecordPointer); forward; - -procedure Proc2 (var IntParRef: OneToFifty); forward; - -procedure Proc3 (var PointerParRef: RecordPointer); forward; - -procedure Proc4; forward; - (* without parameters *) - -procedure Proc5; forward; - (* without parameters *) - -procedure Proc6 ( EnumParVal: Enumeration; - var EnumParRef: Enumeration); forward; - -procedure Proc7 ( Int1ParVal, - Int2ParVal: OneToFifty; - var IntParRef: OneToFifty); forward; - -procedure Proc8 (var Array1ParRef: Array1DimInteger; - var Array2ParRef: Array2DimInteger; - Int1ParVal, - Int2ParVal: integer); forward; - -function Func1 ( Char1ParVal, - Char2ParVal: CapitalLetter): - Enumeration; forward; - -function Func2 (var String1ParRef, - String2ParRef: String30): - boolean; forward; - -function Func3 ( EnumParVal: Enumeration): - boolean; forward; - - -procedure Proc1; (* (PointerParVal: RecordPointer) *) - (* executed once *) -begin - with PointerParVal^.PointerComp^ (* = PointerGlobNext *) do - begin - PointerParVal^.PointerComp^ := PointerGlob^; - PointerParVal^.IntComp := 5; - IntComp := PointerParVal^.IntComp; - PointerComp := PointerParVal^.PointerComp; - Proc3 (PointerComp); - (* PointerParVal^.PointerComp^.PointerComp = PointerGlob^.PointerComp *) - if Discr = Ident1 - then (* executed *) - begin - IntComp := 6; - Proc6 (PointerParVal^.EnumComp, EnumComp); - PointerComp := PointerGlob^.PointerComp; - Proc7 (IntComp, 10, IntComp); - end (* then *) - else (* not executed *) - PointerParVal^ := PointerParVal^.PointerComp^; - end; (* with *) -end; (* Proc1 *) - - -procedure Proc2; (* (var IntParRef: OneToFifty) *) - (* executed once *) - (* InParRef = 3, becomes 7 *) -var - IntLoc: OneToFifty; - EnumLoc: Enumeration; -begin - IntLoc := IntParRef + 10; - repeat (* executed once *) - if Char1Glob = 'A' - then (* executed *) - begin - IntLoc := IntLoc - 1; - IntParRef := IntLoc - IntGlob; - EnumLoc := Ident1; - end (* if *) - until EnumLoc = Ident1; (* true *) -end; (* Proc2 *) - - -procedure Proc3; (* (var PointerParRef: RecordPointer) *) - (* executed once *) - (* PointerParRef becomes PointerGlob *) -begin - if PointerGlob <> nil - then (* executed *) - PointerParRef := PointerGlob^.PointerComp; - Proc7 (10, IntGlob, PointerGlob^.IntComp); -end; (* Proc3 *) - - -procedure Proc4; (* without parameters *) - (* executed once *) -var - BoolLoc: boolean; -begin - BoolLoc := Char1Glob = 'A'; - BoolGlob := BoolLoc or BoolGlob; - Char2Glob := 'B'; -end; (* Proc4 *) - - -procedure Proc5; (* without parameters *) - (* executed once *) -begin - Char1Glob := 'A'; - BoolGlob := false; -end; (* Proc5 *) - - -procedure Proc6; (* ( EnumParVal: Enumeration; - var EnumParRef: Enumeration) *) - (* executed once *) - (* EnumParVal = Ident3, EnumParRef becomes Ident2 *) -begin - EnumParRef := EnumParVal; - if not Func3 (EnumParVal) - then (* not executed *) - EnumParRef := Ident4; - case EnumParVal of - Ident1: EnumParRef := Ident1; - Ident2: if IntGlob > 100 - then EnumParRef := Ident1 - else EnumParRef := Ident4; - Ident3: EnumParRef := Ident2; (* executed *) - Ident4: ; - Ident5: EnumParRef := Ident3; - end; (* case *) -end; (* Proc6 *) - - -procedure Proc7; (* ( Int1ParVal, - Int2ParVal: OneToFifty; - var IntParRef: OneToFifty) *) - (* executed three times *) - (* first call: Int1ParVal = 2, Int2ParVal = 3, *) - (* IntParRef becomes 7 *) - (* second call: Int1ParVal = 10, Int2ParVal = 5, *) - (* IntParRef becomes 17 *) - (* third call: Int1ParVal = 6, Int2ParVal = 10, *) - (* IntParRef becomes 18 *) -var - IntLoc: OneToFifty; -begin - IntLoc := Int1ParVal + 2; - IntParRef := Int2ParVal + IntLoc; -end; (* Proc7 *) - - -procedure Proc8; (* (var Array1ParRef: Array1DimInteger; - var Array2ParRef: Array2DimInteger; - Int1ParVal, - Int2ParVal: integer) *) - (* executed once *) - (* Int1ParVal = 3 *) - (* Int2ParVal = 7 *) -var - IntIndex, - IntLoc: OneToFifty; -begin - IntLoc := Int1ParVal + 5; - Array1ParRef [IntLoc] := Int2ParVal; - Array1ParRef [IntLoc+1] := Array1ParRef [IntLoc]; - Array1ParRef [IntLoc+30] := IntLoc; - for IntIndex := IntLoc to IntLoc+1 do - Array2ParRef [IntLoc, IntIndex] := IntLoc; - Array2ParRef [IntLoc, IntLoc-1] := Array2ParRef [IntLoc, IntLoc-1] + 1; - Array2ParRef [IntLoc+20, IntLoc] := Array1ParRef [IntLoc]; - IntGlob := 5; -end; (* Proc8 *) - - -function Func1; (* (Char1ParVal, - Char2ParVal: CapitalLetter): Enumeration *) - (* executed three times, returns always Ident1 *) - (* first call: Char1ParVal = 'H', Char2ParVal = 'R' *) - (* second call: Char1ParVal = 'A', Char2ParVal = 'C' *) - (* third call: Char1ParVal = 'B', Char2ParVal = 'C' *) -var - Char1Loc, Char2Loc: CapitalLetter; -begin - Char1Loc := Char1ParVal; - Char2Loc := Char1Loc; - if Char2Loc <> Char2ParVal - then (* executed *) - Func1 := Ident1 - else (* not executed *) - begin - Char1Glob := Char1Loc; - Func1 := Ident2; - end; -end; (* Func1 *) - - -function Func2; (* (var String1ParRef, - String2ParRef: String30): boolean *) - (* executed once, returns false *) - (* String1ParRef = 'DHRYSTONE PROGRAM, 1''ST STRING' *) - (* String2ParRef = 'DHRYSTONE PROGRAM, 2''ND STRING' *) -var - IntLoc: OneToThirty; - CharLoc: CapitalLetter; -begin - IntLoc := 2; - while IntLoc <= 2 do (* loop body executed once *) - if Func1 (String1ParRef[IntLoc], - String2ParRef[IntLoc+1]) = Ident1 - then (* executed *) - begin - CharLoc := 'A'; - IntLoc := IntLoc + 1; - end; (* if, while *) - if (CharLoc >= 'W') and (CharLoc < 'Z') - then (* not executed *) - IntLoc := 7; - if CharLoc = 'R' - then (* not executed *) - Func2 := true - else (* executed *) - begin - if String1ParRef > String2ParRef - then (* not executed *) - begin - IntLoc := IntLoc + 7; - IntGlob := IntLoc; - Func2 := true - end - else (* executed *) - Func2 := false; - end; (* if CharLoc *) -end; (* Func2 *) - - -function Func3; (* (EnumParVal: Enumeration): boolean *) - (* executed once, returns true *) - (* EnumParVal = Ident3 *) -var - EnumLoc: Enumeration; -begin - EnumLoc := EnumParVal; - if EnumLoc = Ident3 - then (* executed *) - Func3 := true - else (* not executed *) - Func3 := false; -end; (* Func3 *) - - -begin (* main program, corresponds to procedures *) - (* Main and Proc_0 in the Ada version *) - - (* Initializations *) - - new (NextPointerGlob); - - new (PointerGlob); - - PointerGlob^.PointerComp := NextPointerGlob; - PointerGlob^.Discr := Ident1; - PointerGlob^.EnumComp := Ident3; - PointerGlob^.IntComp := 40; - PointerGlob^.StringComp := 'DHRYSTONE PROGRAM, SOME STRING'; - - String1Glob := 'DHRYSTONE PROGRAM, 1''ST STRING'; - - Array2Glob [8,7] := 10; - - writeln; - writeln ('Dhrystone Benchmark, Version 2.1 (Language: Pascal)'); - writeln; - writeln ('Please give the number of runs through the benchmark: '); - readln (NumberOfRuns); - writeln; - writeln ('Execution starts, ', NumberOfRuns : 7, ' runs through Dhrystone'); - - BeginClock := clock; - - (***************) - (* Start timer *) - (***************) - - for RunIndex := 1 to NumberOfRuns do - begin - - Proc5; - Proc4; - (* Char1Glob = 'A', Char2Glob = 'B', BoolGlob = false *) - Int1Glob := 2; - Int2Glob := 3; - String2Glob := 'DHRYSTONE PROGRAM, 2''ND STRING'; - EnumGlob := Ident2; - BoolGlob := not Func2 (String1Glob, String2Glob); - (* BoolGlob = true *) - while Int1Glob < Int2Glob do (* loop body executed once *) - begin - Int3Glob := 5 * Int1Glob - Int2Glob; - (* Int3Glob = 7 *) - Proc7 (Int1Glob, Int2Glob, Int3Glob); - (* Int3Glob = 7 *) - Int1Glob := Int1Glob + 1; - end; (* while *) - (* Int1Glob = 3 *) - Proc8 (Array1Glob, Array2Glob, Int1Glob, Int3Glob); - (* IntGlob = 5 *) - Proc1 (PointerGlob); - for CharIndex := 'A' to Char2Glob do (* loop body executed twice *) - if EnumGlob = Func1 (CharIndex, 'C') - then (* not executed *) - begin - Proc6 (Ident1, EnumGlob); - String2Glob := 'DHRYSTONE PROGRAM, 3''RD STRING'; - Int2Glob := RunIndex; - IntGlob := RunIndex; - end; - (* Int1Glob = 3, Int2Glob = 3, Int3Glob = 7 *) - Int2Glob := Int2Glob * Int1Glob; - Int1Glob := Int2Glob div Int3Glob; - Int2Glob := 7 * (Int2Glob - Int3Glob) - Int1Glob; - (* Int1Glob = 1, Int2Glob = 13, Int3Glob = 7 *) - Proc2 (Int1Glob); - (* Int1Glob = 5 *) - - end; (* for RunIndex *) - - EndClock := clock; - - (**************) - (* Stop timer *) - (**************) - - writeln ('Execution ends'); - writeln; - writeln ('Final values of the variables used in the benchmark:'); - writeln; - - writeln ('IntGlob: ', IntGlob : 5); - writeln (' should be: 5'); - write ('BoolGlob: '); - if BoolGlob = true - then - writeln ('TRUE') - else - writeln ('FALSE'); - writeln (' should be: TRUE'); - writeln ('Char1Glob: ', Char1Glob); - writeln (' should be: A'); - writeln ('Char2Glob: ', Char2Glob); - writeln (' should be: B'); - writeln ('Array1Glob [8]: ', Array1Glob [8] : 5); - writeln (' should be: 7'); - writeln ('Array2Glob [8,7]: ', Array2Glob [8,7] : 5); - writeln (' should be: NumberOfRuns + 10'); - writeln ('PointerGlob^.Discr: ', ord (PointerGlob^.Discr) : 5); - writeln (' should be: 0'); - writeln ('PointerGlob^.EnumComp: ', ord (PointerGlob^.EnumComp) : 5); - writeln (' should be: 2'); - writeln ('PointerGlob^.IntComp : ', PointerGlob^.IntComp : 5); - writeln (' should be: 17'); - write ('PointerGlob^.StringComp: '); - for I := 1 to 30 do - write (PointerGlob^.StringComp [I]); - writeln; - writeln (' should be: DHRYSTONE PROGRAM, SOME STRING'); - writeln ('NextPointerGlob^.Discr: ', ord (NextPointerGlob^.Discr) : 5); - writeln (' should be: 0'); - writeln ('NextPointerGlob^.EnumComp: ', - ord (NextPointerGlob^.EnumComp) : 5); - writeln (' should be: 1'); - writeln ('NextPointerGlob^.IntComp: ', NextPointerGlob^.IntComp : 5); - writeln (' should be: 18'); - write ('NextPointerGlob^.StringComp: '); - for I := 1 to 30 do - write (NextPointerGlob^.StringComp [I]); - writeln; - writeln (' should be: DHRYSTONE PROGRAM, SOME STRING'); - writeln ('Int1Glob: ', Int1Glob : 5); - writeln (' should be: 5'); - writeln ('Int2Glob: ', Int2Glob : 5); - writeln (' should be: 13'); - writeln ('Int3Glob: ', Int3Glob : 5); - writeln (' should be: 7'); - writeln ('EnumGlob: ', ord (EnumGlob) : 5); - writeln (' should be: 1'); - write ('String1Glob: '); - for I := 1 to 30 do - write (String1Glob [I]); - writeln; - writeln (' should be: DHRYSTONE PROGRAM, 1''ST STRING'); - write ('String2Glob: '); - for I := 1 to 30 do - write (String2Glob [I]); - writeln; - writeln (' should be: DHRYSTONE PROGRAM, 2''ND STRING'); - writeln; - writeln; - - SumClocks := EndClock - BeginClock; - - if SumClocks < TooSmallTime - then - begin - writeln ('Measured time too small to obtain meaningful results'); - writeln ('Please increase number of runs'); - writeln; - end - else - begin - Microseconds := SumClocks * (MicrosecondsPerClock / NumberOfRuns); - (* Brackets to prevent integer overflow *) - DhrystonesPerSecond := NumberOfRuns * (ClocksPerSecond / SumClocks); - write ('Microseconds for one run through Dhrystone: '); - writeln (Microseconds : 8 : 1); - write ('Dhrystones per Second: '); - writeln (DhrystonesPerSecond : 8 : 1); - writeln; - end; - -end. //GO.SYSIN DD dhry.p-2 echo dhry_c.dif 1>&2 sed >dhry_c.dif <<'//GO.SYSIN DD dhry_c.dif' 's/^-//' -7c7 -< * Version: C, Version 2.1 ---- -> * Version: C, Version 2.0 -9c9 -< * File: dhry.h (part 1 of 3) ---- -> * File: dhry_global.h (part 1 of 3) -11c11 -< * Date: May 25, 1988 ---- -> * Date: March 3, 1988 -30c30 -< * In addition, Berkeley UNIX system calls "times ()" or "time ()" ---- -> * In addition, UNIX system calls "times ()" or "time ()" -44c44 -< * Please send results to Rick Richardson and/or Reinhold Weicker. ---- -> * Please send results to Reinhold Weicker and/or Rick Richardson. -59c59 -< * History: This version C/2.1 has been made for two reasons: ---- -> * History: This version C/2.0 has been made for two reasons: -123,129d122 -< * Version 2.1 is identical to version 2.0 distributed via -< * the UNIX network Usenet in March 1988 except that it corrects -< * some minor deficiencies that were found by users of version 2.0. -< * The only change within the measurement loop is that a -< * non-executed "else" part was added to the "if" statement in -< * Func_3, and a non-executed "else" part removed from Proc_3. -< * -165,167c158,160 -< * -DHZ=nnn -< * In Berkeley UNIX, the function "times" returns process -< * time in 1/HZ seconds, with HZ = 60 for most systems. ---- -> * -DHZ=nnn (default: 60) -> * The function "times" returns process times in -> * 1/HZ seconds, with HZ = 60 for most systems. -169c162 -< * A VALUE. ---- -> * THE DEFAULT VALUE. -176,178c169,171 -< * - dhry.h (this file, containing global definitions and comments) -< * - dhry_1.c (containing the code corresponding to Ada package Pack_1) -< * - dhry_2.c (containing the code corresponding to Ada package Pack_2) ---- -> * - dhry_global.h (this file, containing global definitions and comments) -> * - dhry_pack_1.c (containing the code corresponding to Ada package Pack_1) -> * - dhry_pack_2.c (containing the code corresponding to Ada package Pack_2) -350a344 -> #ifndef TIMES -353,354c347,354 -< /* Use times(2) time function unless */ -< /* explicitly defined otherwise */ ---- -> #endif -> /* Use "times" function for measurement */ -> /* unless explicitly defined otherwise */ -> #ifndef HZ -> #define HZ 60 -> #endif -> /* Use HZ = 60 for "times" function */ -> /* unless explicitly defined otherwise */ -363c363 -< /* Berkeley UNIX C returns process times in seconds/HZ */ ---- -> /* UNIX C returns process times in seconds/HZ */ -7c7 -< * Version: C, Version 2.1 ---- -> * Version: C, Version 2.0 -9c9 -< * File: dhry_1.c (part 2 of 3) ---- -> * File: dhry_pack_1.c (part 2 of 3) -11c11 -< * Date: May 25, 1988 ---- -> * Date: March 3, 1988 -18c18 -< #include "dhry.h" ---- -> #include "dhry_global.h" -50,51d49 -< #define Too_Small_Time 120 -< /* Measurements should last at least about 2 seconds */ -55a54,55 -> #endif -> -58d57 -< #endif -73a73 -> -84a85 -> -99,100c100,102 -< /* Was missing in published program. Without this statement, */ -< /* Arr_2_Glob [8][7] would have an undefined value. */ ---- -> /* Was missing in published program. Without this */ -> /* initialization, Arr_2_Glob [8][7] would have an */ -> /* undefined value. */ -105c107 -< printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n"); ---- -> printf ("Dhrystone Benchmark, Version 2.0 (Language: C)\n"); -281c283 -< /******************/ ---- -> /**********************/ -338c340 -< /******************/ ---- -> /**********************/ -347a350,351 -> else /* not executed */ -> Int_Glob = 100; -349a354 -> -7c7 -< * Version: C, Version 2.1 ---- -> * Version: C, Version 2.0 -9c9 -< * File: dhry_2.c (part 3 of 3) ---- -> * File: dhry_pack_2.c (part 3 of 3) -11c11 -< * Date: May 25, 1988 ---- -> * Date: March 3, 1988 -18c18 -< #include "dhry.h" ---- -> #include "dhry_global.h" -189,190d188 -< else /* not executed */ -< return (false); //GO.SYSIN DD dhry_c.dif echo submit.frm 1>&2 sed >submit.frm <<'//GO.SYSIN DD submit.frm' 's/^-//' -DHRYSTONE 2.1 BENCHMARK REPORTING FORM -MANUF: -MODEL: -PROC: -CLOCK: -OS: -OVERSION: -COMPILER: -CVERSION: -OPTIONS: -NOREG: -REG: -NOTES: -DATE: -SUBMITTER: -CODESIZE: -MAILTO: uunet!pcrat!dry2 //GO.SYSIN DD submit.frm