reeder@reed.UUCP (Doug Reeder) (10/30/89)
This is primarily for Tim Smithers, whom I could not reach by mail, but others may be interested. send the following commands as the body of an email message to nistlib@cmr.icst.nbs.gov send doc from info send index send index from stones -- Doug Reeder USENET: ...!tektronix!reed!reeder Box 722 Reed College BITNET: reeder@reed.BITNET Portland, OR 97202 from ARPA: tektronix!reed!reeder@berkeley.EDU (503) 777-1551 "A blaster can point two ways." -Salvor Hardin
6600john%ucsbuxa@hub.ucsb.edu (Tazz Man) (02/22/90)
I am sure that there are others out there who are just a curious about compiler performance as I am. Here is a suggestion: We come up with a benchmark which exercises the language (Pascal or M2) in a way as to simulate an actual program. This program should be machine and compiler independent (meaning, no nifty optimization tricks). The program should then be run on as many different machines and different compilers as possible (with out any resident programs running, of course). The results should then be posted. If people find time to undertake this I will compile all of the results and present them. John Bernstein 6600john@ucsbuxa.ucsb.edu
bigelow@hpfcso.HP.COM (Jim Bigelow) (02/22/90)
Concerning pascal benchmarks, how about using the drystone benchmark? I have included the source incase you don't have it. Jim Bigelow S300 Pascal Colorado Langauge Lab HP, Ft. Collins ---- $standard_level 'hp_modcal'$ (* **************************************************************************** * * "DHRYSTONE" Benchmark Program * ----------------------------- * * Version: Pascal, Version 2.1 * * File: dhry.p * * Date: May 25, 1988 * * Author: Reinhold P. Weicker * Siemens AG, E STE 35 * Postfach 3240 * 8520 Erlangen * Germany (West) * Phone: [xxx-49]-9131-7-20330 * (8-17 Central European Time) * Usenet: ..!mcvax!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. * * Slight modifications made for compilation using HP Pascal * Jim Bigelow, S300 HP Pascal, Colorado Language Lab, * HP, Ft. Collins, Colorado * * Collection of Results: * Reinhold Weicker (address see above) and * * Rick Richardson * PC Research. Inc. * 94 Apple Orchard Drive * Tinton Falls, NJ 07724 * Phone: (201) 834-1378 (9-17 EST) * Usenet: ...!seismo!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 des 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. * **************************************************************************** *) 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 *) function $alias '_clock'$ clock :integer; external; 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.