Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/5/84; site reed.UUCP
Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!vax135!cornell!uw-beaver!tektronix!reed!maclab
From: maclab@reed.UUCP (S.Gillespie/Mac Dev. Lab)
Newsgroups: net.sources.mac
Subject: Rascal Benchmarks (Long)
Message-ID: <2110@reed.UUCP>
Date: Tue, 5-Nov-85 17:08:45 EST
Article-I.D.: reed.2110
Posted: Tue Nov 5 17:08:45 1985
Date-Received: Thu, 7-Nov-85 05:20:44 EST
Organization: Reed College, Portland, Oregon
Lines: 619
As a follow-up to the recent Byte review of 5 Macintosh C compilers, I have
compared Rascal's performance on the same benchmarks. Included are
time comparisons, notes, and Rascal sources. This is by no means a
stand-alone article -- I strongly recommend that you use this information
*in conjunction* with the Byte article, should you wish to draw
specific conclusions about these benchmarks.
Rascal is certainly not the fastest of the development systems, in terms
of these benchmarks, but I think it compares rather favorably with the C's.
Scott Gillespie
Reed College
Claimer: As a member of the Rascal development team, I am biased
beyond a doubt, but I hope you will find this to be a fair
and honest evaluation.
{decvax, ucbvax, pur-ee, uw-beaver, masscomp, cbosg, aat, mit-ems,
psu-cs, uoregon, orstcs, ihnp4, uf-cgrl, ssc-vax}!tektronix
\
+--!reed!maclab
{teneron, ogcvax, muddcs, cadic, oresoft, grpwre, /
harvard, psu-cs, omen, isonvax, nsc-pdc}----------+
---------------------------------------------------------------------------
Rascal Benchmarks
In a recent issue of Byte magazine (November 1985 Vol. 10, No. 12), Tim Field
reviewed 5 Macintosh development systems ("Five C Compilers for the
Macintosh," page 275), and included a number of benchmarks for timing
comparison. Because C is part of Rascal's heritage, we found it extremely
easy to translate the C benchmark sources into Rascal. What follows are
benchmark times, sources and notes which put Rascal's performance in
perspective with the C compilers. Complete C sources and useful descriptions
of the various benchmarks may be found in Mr. Field's article.
Execution Times
(In Seconds)
Rascal SoftWorks C Mac C Aztec C Hippo-C MegaMax C
Frame
Normal 0.11 0.13 0.13 0.10 0.25 0.10
Register 0.07 0.08 n.a. 0.05 n.a. 0.05
Pointer
Normal 37.93 24.33 26.60 25.50 33.23 30.02
Register 27.51 11.15 n.a. 13.15 n.a. 18.93
Intmath
Normal 5.33 30.05 5.03 5.10 15.93 5.05
Register 3.12 26.73 n.a. 2.70 n.a. 2.78
Sieve
Normal 6.77 8.83 7.98 6.20 12.65 6.20
Register 4.51 4.73 n.a. 3.88 n.a. 4.17
Qsort
Normal * 157.08 63.92 68.43 * 93.38
Register * 93.72 n.a. 50.87 n.a. 70.80
Float
Normal 149.75** 332.77 n.a. 268.22 n.a. 334.32
Fib
Normal 36.66 28.60 31.67 24.72 47.22 25.97
Interface
Normal 74.20 59.18 71.40 56.22 78.47 72.00
* BenchMark failed, due to insufficient stack space (>24K stack required)
** The Rascal Compiler does not support direct floating point calculations:
this benchmark was performed using SANE floating point calls (see
source, and notes below).
Benchmark Notes
All Benchmark programs were:
1) Compiled, Linked and Executed with a pre-release Rascal Development system
(Dated v.85.10.28.spg). This version of the development system is frozen
(except for minor cosmetic changes), and will be released as the 'final'
version as soon as we finish the documentation.
2) Executed with Rascal's built-in millisecond timer disabled (the timer may
be disabled with Rascal's new configuration dialog box), since the millisecond
timer steals a fair chunk of processor time (~10%).
3) Written to mimic, as much as possible, not only the functionality of the
given C benchmarks, but also their appearance and structure. This included
using curly-braces ( { } ) in place of begin/end (either set is allowed in
Rascal).
Individual Benchmark Notes
Below are a few individual comments on some of the benchmarks -- for a
complete description of all benchmarks and for an explanation of what element
of the development system each tests, see the Byte article.
Qsort
Both Rascal and Hippo-C failed this benchmark due to insufficient stack
space. It should be noted that the particular sorting algorithm given
requires 1 level of recursion for every element, therefore 1000 levels of
recursion are required for Qsort -- Rascal was able to perform the Qsort test
on a smaller array, which required fewer recursion levels. Also note that
there are several disastrous typos in the Byte listing of this benchmark, so
take care when trying to duplicate it in your own favorite language!
Float
The given benchmark assumed built-in Compiler support for floating point
calculations -- neither Mac C, nor Hippo-C nor Rascal provide this amenity, so
the Rascal version of this benchmark should not be used for direct speed
comparison with the other C compilers. Rascal floating point calculations are
carried out using SANE (Standard Apple Numeric Environment) procedure calls
(see the Rascal source). We might point out, however, that although
convenience is sacrificed with this method, you will note that the Rascal
benchmark was twice as fast as the average of the other C compiler versions.
Also, the C floating point numbers are 32 bit double floats, and Rascal's SANE
floats are 80 bit extended precision floats...
Interface
The intent of this benchmark is to test the effectiveness of a language's
interface calls to Macintosh ROM routines. The particular ROM routine chosen
for this test (GetNextEvent) is not well suited for benchmark testing -- the
amount of time spent within GetNextEvent can vary widely between different
systems and Macintosh configurations: the presence of drivers and desk
accessories may slow down the benchmark considerably, so beware.
Benchmark Listings
All benchmark sources were created using an outline source file containing
three procedures: Bench(), _Init() and _Key(c,mods: integer). _Init and _Key
are Rascal entry points. _Init is the initial entry point (_Init is called
before any other Rascal procedure), and _Key is called whenever the user
presses a key on the keyboard. Both _Init and _Key, in the benchmark sources,
call the procedure Bench(): within procedure Bench(), each benchmark was
written. Therefore, the Bench() of a Rascal benchmark is analogous to the
main() of the C benchmarks. The _Key procedure is there so that the benchmark
may be repeated by pressing a key.
Within the Bench() procedure, are calls Start() and Stop() (analogous to the
'startup' and 'done' include files in the C benchmarks). Start() and Stop()
are library routines which were written for these benchmark tests, and are
located in __BenchMarkLib (listing is included here). Start and Stop time
with both Rascal's millisecond timer, and the Macintosh's built-in tick count:
since the millisecond timer was disabled for the actual benchmark tests, the
millisecond value was ignored.
Each benchmark source contains time information at the top, as well as the
final file size. These file sizes, you will note, are extremely small
compared to the file sizes given in the Byte article: this is because we did
not follow the Byte requirement that all benchmarks be stand-alone
applications. For a proper comparison with the file sizes in Byte, add about
18.5K to each of the file sizes given in the Rascal benchmark sources -- all
of these benchmarks may be made into stand-alone applications with no source
modifications (another method of creating Rascal stand-alone applications
would add about 3.5K, instead of 18.5K, but would require source
modification).
Where times are given for register versions of the Rascal benchmarks, the
changes made to the source are very simple. To declare a local register
variable in Rascal (up to 5 are allowed), one just puts the keyword 'register'
between the identifer-list and the type, in the variable declaration:
Var
x,y,z: register integer;
The Sources:
(*________________________FRAME_____________________________*)
Program Frame;
(*
.11 seconds -- Non-Register
.07 seconds -- Register
File Size: 536 bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO :;
Procedure Bench();
Const
Count = 10000;
Var
i: Integer;
{
Start();
loop(,i:=0,++i,i=10000);
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*_________________________POINTER___________________________*)
Program Pointer;
(*
37.93 seconds -- Non-Register
27.51 seconds -- Register
File Size: 622 bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO :;
Procedure Bench();
Const
Count = 10000;
Allotted = 128;
Var
WorkArea: Byte[Allotted];
Ptr: Ptrb;
i: Integer;
{
Start();
loop(,i:=0,++i,i=Count) {
ptr := @WorkArea;
loop(ptr<(workarea+allotted),,,!(ptr<(workarea+allotted))) {
ptr^ := ' ';
++ptr;
};
};
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*___________________________INTMATH__________________________*)
Program IntMath;
(*
5.33 seconds -- Non-Register
3.12 seconds -- Register
File Size: 1148 bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO :;
Procedure Bench();
Const
Count = 10000;
Var
i,j,k: Integer;
{
Start();
Loop(,i:=0,++i,i=Count) {
j := 240; k := 15;
j := (k*(j/k));
j := (k*(j/k));
j := (k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k);
k := (j-k-k-k-k-k-k-k-k-k-k-k-k-k-k-k);
j := (j<<4); k := (k<<4);
j := (k*(j/k));
j := (k*(j/k));
j := (k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k);
k := (j-k-k-k-k-k-k-k-k-k-k-k-k-k-k-k);
j := (j<<4); k := (k<<4);
j := (k*(j/k));
j := (k*(j/k));
j := (k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k);
k := (j-k-k-k-k-k-k-k-k-k-k-k-k-k-k-k);
};
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*__________________________SIEVE___________________________*)
Program Sieve;
(*
6.77 seconds -- Non-Register
4.51 seconds -- Register
File Size: 762 bytes
*)
Uses
(*$U+*) uMemtypes;
Link __BenchMarkLib, __IO, __ExtendIO :;
Const
Size = 8190;
Var
Flags: Byte[8191 ];
Procedure Bench();
Var
i,prime,k,count,iter: Integer;
{
Start();
Loop(,iter:=1,,++iter>10) {
count := 0;
loop(,i:=0,++i,i>Size)
flags[i]:=True;
loop(,i:=0,++i,i>Size)
if flags[i] Then {
prime := i+i+3;
k:=i+prime;
loop(k=Size)
flags[k]:=False;
++count;
};
};
Stop();
Writeln();
WriteIntNs(Count);
WriteString(" : Primes.");
Writeln();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*___________________________FLOAT__________________________*)
Program Float;
(*
149.75 seconds -- Non-Register
File Size: 1062 bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO, __Sane :;
const COUNT=10000;
var a,b,c:Float;
Procedure Bench();
var i:integer;
{
Start();
Lqfillf(3141597,-6,a);
Lqfillf(17839032,-3,b);
loop(,i:=0,++i,i=count)
{
c:=a;
mulf(b,c); (* c = c*b *)
divf(a,c); (* c = c/a *)
c:=a; mulf(b,c); divf(a,c);
c:=a; mulf(b,c); divf(a,c);
c:=a; mulf(b,c); divf(a,c);
c:=a; mulf(b,c); divf(a,c);
c:=a; mulf(b,c); divf(a,c);
c:=a; mulf(b,c); divf(a,c);
};
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*____________________________FIB_________________________*)
Program FIB;
(*
36.66 seconds -- Non-Register
File Size: 678 bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO :;
Function Fib(x: Integer): Longint;
{
If x>2 Then
Return(Fib(x-1) + Fib(x-2))
Else
Return(1);
};
Procedure Bench();
Const
NTimes = 10;
Number = 24;
Var
i: Integer;
Value: Longint;
{
Start();
Loop(,i:=0,++i,i=NTimes)
Value := Fib(Number);
Stop();
Writeln();
Writestring("Value: ");
WriteLongNS(Value);
Writeln();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
(*__________________________INTERFACE___________________________*)
Program Interface;
(*
74.20 seconds -- Non-Register
File Size: 696 bytes
*)
Uses __ToolTraps,
(*$U+*) uToolIntf;
Link __BenchMarkLib, __IO, __ExtendIO :;
Procedure Bench();
Const
Count = 10000;
Var
i, M1,M2 : Integer;
Bool1,Bool2 : Boolean;
ER1,ER2 : EventRecord;
{
Start();
M1 := -1;
M2 := -1;
Loop(,i:=0,++i,i=Count) {
Bool1 := GetNextEvent(M1,@ER1);
Bool2 := GetNextEvent(m2,@ER2);
Bool1 := GetNextEvent(M1,@ER1);
Bool2 := GetNextEvent(m2,@ER2);
Bool1 := GetNextEvent(M1,@ER1);
Bool2 := GetNextEvent(m2,@ER2);
Bool1 := GetNextEvent(M1,@ER1);
Bool2 := GetNextEvent(m2,@ER2);
};
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
(*___________________________ __BENCHMARKLIB __________________________*)
Program __BenchMarkLib;
Uses __ToolBox;
Link __IO, __ExtendIO :;
Var
MTime: Longint;
TTime: Longint;
Proc Start();
{
Writeln();
WriteString("Starting Timers...");
TTime:= -TickCount();
ResetTimer();
};
Proc Stop();
Var t: integer;
{
TimerVal(@MTime);
TTime += TickCount();
Writeln();
WriteString(" Milliseconds: ");
Writelongns(MTime);
Writeln();
WriteString(" Seconds: ");
Writeintns(TTime/60);
WriteChar('.');
T := ((TTime mod 60)*100)/60;
If T<10 Then WriteChar('0');
Writeintns(T);
Writeln();
Writeln();
};
(*___________________________BENCH__________________________*)
Program Bench;
(*
seconds -- Non-Register
seconds -- Register
File Size: bytes
*)
Link __BenchMarkLib, __IO, __ExtendIO :;
Procedure Bench();
{
Start();
Stop();
};
Procedure _Key(c,mods: integer);
{
Bench();
};
Procedure _Init();
{
Bench();
};
End of Article...