[net.sources] Latest Drystone Benchmarks

rer@vaximile.UUCP (R.RICHARDSON) (10/15/85)

/*
 *	"DHRYSTONE" Benchmark Program
 *
 *	Version:	C/1
 *	Date:		12/01/84, RESULTS updated 10/15/85
 *	Author:		Reinhold P. Weicker,  CACM Vol 27, No 10, 10/84 pg. 1013
 *			Translated from ADA by Rick Richardson
 *			Every method to preserve ADA-likeness has been used,
 *			at the expense of C-ness.
 *	Compile:	cc -O dry.c -o drynr			: No registers
 *			cc -O -DREG=register dry.c -o dryr	: Registers
 *	Defines:	Defines are provided for old C compiler's
 *			which don't have enums, and can't assign structures.
 *			The time(2) function is library dependant; One is
 *			provided for CI-C86.  Your compiler may be different.
 *	Run:		drynr; dryr
 *			50000 Runs are made and the time is printed
 *	Results:	If you get any new machine/OS results, please send to:
 *				..!houxm!vaximile!rer
 *			and thanks to all that do.  Space prevents listing
 *			the names of those who have provided some of these
 *			results.
 *
 * MACHINE	MICROPROCESSOR	OPERATING	COMPILER	DHRYSTONES/SEC.
 * TYPE				SYSTEM				NO REG	REGS
 * --------------------------	------------	-----------	---------------
 * IBM PC/XT	8088-4.77Mhz	PCDOS 2.1	CI-C86 2.1	????	????
 * IBM PC/XT	8088-4.77Mhz	PC/IX		cc		????	????
 * Lisa		68000-7.7Mhz	????		??		????	????
 * IBM PC/XT	8088-4.77Mhz	VENIX/86 2.0	cc		 297	 324
 * ATT PC6300	8086-8Mhz	MSDOS 2.11	b16cc 2.0	 632	 684
 * IBM PC/AT	80286-6Mhz	PCDOS 3.0	CI-C86 2.1	 666	 684
 * Macintosh	68000-7.7Mhz	-		MegaMax C 2.0	 661	 709
 * ATT PC6300	8086-8Mhz	MSDOS 2.11	CI-C86 2.20M	 769	 769
 * ATT 3B2/300	MAC32-?Mhz	UNIX 5.0.2	cc		 735	 806
 * Fast Mac	68000-7.7Mhz	-		MegaMax C 2.0	 839	 904 +
 * IBM PC/AT	80286-6Mhz	VENIX/86 2.1	cc		 961	1000
 * VAX 11/750	-		VMS		VAX-11 C 2.0	 958	1091
 * ATT PC7300	68010-10Mhz	UNIX 5.2	cc		1041	1111
 * Sun2/120	68010-10Mhz	Sun 4.2BSD	cc		1136	1219
 * PDP 11/70	-		UNIX 5.2	cc		1162	1250
 * IBM PC/AT	80286-7.5Mhz	VENIX/86 2.1	cc		1190	1315 *
 * VAX 11/780	-		UNIX 5.2	cc		1515	1562
 * ATT 3B20	-		UNIX 5.2	cc		1515	1724
 * Gould PN6005	-		UTX 1.1(4.2BSD)	cc		1675	1964
 * Amdahl 580	-		UTS 5.0 Rel 1.2	cc Ver. 1.5    23076   23076
 *
 *   * 15Mhz crystal substituted for original 12Mhz;
 *   + This Macintosh was upgraded from 128K to 512K in such a way that
 *     the new 384K of memory is not slowed down by video generator accesses.
 *
 **************************************************************************
 *
 *	The following program contains statements of a high-level programming
 *	language (C) in a distribution considered representative:
 *
 *	assignments			53%
 *	control statements		32%
 *	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.
 *
 *	The combination of these three aspects is balanced only approximately.
 *
 *	The program does not compute anything meaningfull, but it is
 *	syntactically and semantically correct.
 *
 */

/* Compiler dependent options */
#undef	NOENUM			/* Define if compiler has no enum's */
#undef	NOSTRUCTASSIGN		/* Define if compiler can't assign structures */
#undef	NOTIME			/* Define if no time() function in library */

#ifdef	NOSTRUCTASSIGN
#define	structassign(d, s)	memcpy(&(d), &(s), sizeof(d))
#else
#define	structassign(d, s)	d = s
#endif

#ifdef	NOENUM
#define	Ident1	1
#define	Ident2	2
#define	Ident3	3
#define	Ident4	4
#define	Ident5	5
typedef int	Enumeration;
#else
typedef enum	{Ident1, Ident2, Ident3, Ident4, Ident5} Enumeration;
#endif

typedef int	OneToThirty;
typedef int	OneToFifty;
typedef char	CapitalLetter;
typedef char	String30[31];
typedef int	Array1Dim[51];
typedef int	Array2Dim[51][51];

struct	Record
{
	struct Record		*PtrComp;
	Enumeration		Discr;
	Enumeration		EnumComp;
	OneToFifty		IntComp;
	String30		StringComp;
};

typedef struct Record 	RecordType;
typedef RecordType *	RecordPtr;
typedef int		boolean;

#define	NULL		0
#define	TRUE		1
#define	FALSE		0

#ifndef REG
#define	REG
#endif

extern Enumeration	Func1();
extern boolean		Func2();

main()
{
	Proc0();
}

/*
 * Package 1
 */
int		IntGlob;
boolean		BoolGlob;
char		Char1Glob;
char		Char2Glob;
Array1Dim	Array1Glob;
Array2Dim	Array2Glob;
RecordPtr	PtrGlb;
RecordPtr	PtrGlbNext;

Proc0()
{
	OneToFifty		IntLoc1;
	REG OneToFifty		IntLoc2;
	OneToFifty		IntLoc3;
	REG char		CharLoc;
	REG char		CharIndex;
	Enumeration	 	EnumLoc;
	String30		String1Loc;
	String30		String2Loc;

#define LOOPS		50000
long			time();
long			starttime;
long			benchtime;
long			nulltime;
register unsigned int	i;
starttime = time(0);
for (i = 0; i < LOOPS; ++i);
nulltime = time(0) - starttime;

	PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
	PtrGlb = (RecordPtr) malloc(sizeof(RecordType));
	PtrGlb->PtrComp = PtrGlbNext;
	PtrGlb->Discr = Ident1;
	PtrGlb->EnumComp = Ident3;
	PtrGlb->IntComp = 40;
	strcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING");

/*****************
-- Start Timer --
*****************/
starttime = time(0);
for (i = 0; i < LOOPS; ++i)
{

	Proc5();
	Proc4();
	IntLoc1 = 2;
	IntLoc2 = 3;
	strcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
	EnumLoc = Ident2;
	BoolGlob = ! Func2(String1Loc, String2Loc);
	while (IntLoc1 < IntLoc2)
	{
		IntLoc3 = 5 * IntLoc1 - IntLoc2;
		Proc7(IntLoc1, IntLoc2, &IntLoc3);
		++IntLoc1;
	}
	Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3);
	Proc1(PtrGlb);
	for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex)
		if (EnumLoc == Func1(CharIndex, 'C'))
			Proc6(Ident1, &EnumLoc);
	IntLoc3 = IntLoc2 * IntLoc1;
	IntLoc2 = IntLoc3 / IntLoc1;
	IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1;
	Proc2(&IntLoc1);

/*****************
-- Stop Timer --
*****************/
}
benchtime = time(0) - starttime - nulltime;
printf("Dhrystone time for %ld passes = %ld\n", (long) LOOPS, benchtime);
printf("This machine benchmarks at %ld dhrystones/second\n",
	((long) LOOPS) / benchtime);

}

Proc1(PtrParIn)
REG RecordPtr	PtrParIn;
{
#define	NextRecord	(*(PtrParIn->PtrComp))

	structassign(NextRecord, *PtrGlb);
	PtrParIn->IntComp = 5;
	NextRecord.IntComp = PtrParIn->IntComp;
	NextRecord.PtrComp = PtrParIn->PtrComp;
	Proc3(NextRecord.PtrComp);
	if (NextRecord.Discr == Ident1)
	{
		NextRecord.IntComp = 6;
		Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
		NextRecord.PtrComp = PtrGlb->PtrComp;
		Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp);
	}
	else
		structassign(*PtrParIn, NextRecord);

#undef	NextRecord
}

Proc2(IntParIO)
OneToFifty	*IntParIO;
{
	REG OneToFifty		IntLoc;
	REG Enumeration		EnumLoc;

	IntLoc = *IntParIO + 10;
	for(;;)
	{
		if (Char1Glob == 'A')
		{
			--IntLoc;
			*IntParIO = IntLoc - IntGlob;
			EnumLoc = Ident1;
		}
		if (EnumLoc == Ident1)
			break;
	}
}

Proc3(PtrParOut)
RecordPtr	*PtrParOut;
{
	if (PtrGlb != NULL)
		*PtrParOut = PtrGlb->PtrComp;
	else
		IntGlob = 100;
	Proc7(10, IntGlob, &PtrGlb->IntComp);
}

Proc4()
{
	REG boolean	BoolLoc;

	BoolLoc = Char1Glob == 'A';
	BoolLoc |= BoolGlob;
	Char2Glob = 'B';
}

Proc5()
{
	Char1Glob = 'A';
	BoolGlob = FALSE;
}

extern boolean Func3();

Proc6(EnumParIn, EnumParOut)
REG Enumeration	EnumParIn;
REG Enumeration	*EnumParOut;
{
	*EnumParOut = EnumParIn;
	if (! Func3(EnumParIn) )
		*EnumParOut = Ident4;
	switch (EnumParIn)
	{
	case Ident1:	*EnumParOut = Ident1; break;
	case Ident2:	if (IntGlob > 100) *EnumParOut = Ident1;
			else *EnumParOut = Ident4;
			break;
	case Ident3:	*EnumParOut = Ident2; break;
	case Ident4:	break;
	case Ident5:	*EnumParOut = Ident3;
	}
}

Proc7(IntParI1, IntParI2, IntParOut)
OneToFifty	IntParI1;
OneToFifty	IntParI2;
OneToFifty	*IntParOut;
{
	REG OneToFifty	IntLoc;

	IntLoc = IntParI1 + 2;
	*IntParOut = IntParI2 + IntLoc;
}

Proc8(Array1Par, Array2Par, IntParI1, IntParI2)
Array1Dim	Array1Par;
Array2Dim	Array2Par;
OneToFifty	IntParI1;
OneToFifty	IntParI2;
{
	REG OneToFifty	IntLoc;
	REG OneToFifty	IntIndex;

	IntLoc = IntParI1 + 5;
	Array1Par[IntLoc] = IntParI2;
	Array1Par[IntLoc+1] = Array1Par[IntLoc];
	Array1Par[IntLoc+30] = IntLoc;
	for (IntIndex = IntLoc; IntIndex <= (IntLoc+1); ++IntIndex)
		Array2Par[IntLoc][IntIndex] = IntLoc;
	++Array2Par[IntLoc][IntLoc-1];
	Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc];
	IntGlob = 5;
}

Enumeration Func1(CharPar1, CharPar2)
CapitalLetter	CharPar1;
CapitalLetter	CharPar2;
{
	REG CapitalLetter	CharLoc1;
	REG CapitalLetter	CharLoc2;

	CharLoc1 = CharPar1;
	CharLoc2 = CharLoc1;
	if (CharLoc2 != CharPar2)
		return (Ident1);
	else
		return (Ident2);
}

boolean Func2(StrParI1, StrParI2)
String30	StrParI1;
String30	StrParI2;
{
	REG OneToThirty		IntLoc;
	REG CapitalLetter	CharLoc;

	IntLoc = 1;
	while (IntLoc <= 1)
		if (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1)
		{
			CharLoc = 'A';
			++IntLoc;
		}
	if (CharLoc >= 'W' && CharLoc <= 'Z')
		IntLoc = 7;
	if (CharLoc == 'X')
		return(TRUE);
	else
	{
		if (strcmp(StrParI1, StrParI2) > 0)
		{
			IntLoc += 7;
			return (TRUE);
		}
		else
			return (FALSE);
	}
}

boolean Func3(EnumParIn)
REG Enumeration	EnumParIn;
{
	REG Enumeration	EnumLoc;

	EnumLoc = EnumParIn;
	if (EnumLoc == Ident3) return (TRUE);
	return (FALSE);
}

#ifdef	NOSTRUCTASSIGN
memcpy(d, s, l)
register char	*d;
register char	*s;
int	l;
{
	while (l--) *d++ = *s++;
}
#endif

/*
 *	Library function for compilers with no time(2) function in the
 *	library.
 */
#ifdef	NOTIME
long	time(p)
long	*p;
{		/* CI-C86 time function - don't use around midnight */
	long	t;
	struct regval {unsigned int ax,bx,cx,dx,si,di,ds,es; } regs;

	regs.ax = 0x2c00;
	sysint21(&regs, &regs);
	t = ((regs.cx>>8)*60L + (regs.cx & 0xff))*60L + (regs.dx>>8);
	if (p) *p = t;
	return t;
}
#endif

chris@umcp-cs.UUCP (Chris Torek) (10/17/85)

Here are some changes to get more accurate results under 4.2 and
4.3 BSD; and here is the result of running the benchmarks on our
shiny new 8600 (not yet even fully installed, but already running
4.3BSD... for the moment, at least):

 * MACHINE	MICROPROCESSOR	OPERATING	COMPILER	DHRYSTONES/SEC.
 * TYPE				SYSTEM				NO REG	REGS
 * --------------------------	------------	-----------	---------------
 * VAX 8600	-		4.3BSD		cc		7092	7153

The speed of the 8600 is quite impressive.

Oh yes, the changes.  Without these I get 7142 for both `NO REG'
and `REG', by the way.

*** dry.c.old	Thu Oct 17 01:55:55 1985
--- dry.c	Thu Oct 17 02:23:02 1985
***************
*** 156,166 ****
  #define LOOPS		50000
  long			time();
! long			starttime;
! long			benchtime;
! long			nulltime;
  register unsigned int	i;
! starttime = time(0);
  for (i = 0; i < LOOPS; ++i);
! nulltime = time(0) - starttime;
  
  	PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
--- 156,167 ----
  #define LOOPS		50000
  long			time();
! long			starttime, startmil;
! long			benchtime, benchmil;
! long			nulltime, nullmil;
  register unsigned int	i;
! gettime(&starttime, &startmil);
  for (i = 0; i < LOOPS; ++i);
! gettime(&nulltime, &nullmil);
! timesub(&nulltime, &nullmil, starttime, startmil);
  
  	PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
***************
*** 175,179 ****
  -- Start Timer --
  *****************/
! starttime = time(0);
  for (i = 0; i < LOOPS; ++i)
  {
--- 176,180 ----
  -- Start Timer --
  *****************/
! gettime(&starttime, &startmil);
  for (i = 0; i < LOOPS; ++i)
  {
***************
*** 206,213 ****
  *****************/
  }
! benchtime = time(0) - starttime - nulltime;
! printf("Dhrystone time for %ld passes = %ld\n", (long) LOOPS, benchtime);
! printf("This machine benchmarks at %ld dhrystones/second\n",
! 	((long) LOOPS) / benchtime);
  
  }
--- 207,217 ----
  *****************/
  }
! gettime(&benchtime, &benchmil);
! timesub(&benchtime, &benchmil, starttime, startmil);
! timesub(&benchtime, &benchmil, nulltime, nullmil);
! printf("Dhrystone time for %ld passes = %ld.%03d\n", (long) LOOPS,
! 	benchtime, benchmil);
! printf("This machine benchmarks at %8.0f dhrystones/second\n",
! 	(double)LOOPS / ((double)benchtime + (benchmil / 1000.0)));
  
  }
***************
*** 415,417 ****
--- 419,481 ----
  	return t;
  }
+ #endif
+ 
+ #include <signal.h>		/* horrible hack to detect 4.[23]BSD */
+ #ifdef SIGVTALRM
+ #define GETTIMEOFDAY
+ #endif
+ 
+ /*
+  * Gettime gets the time in seconds and milliseconds.  timesub subtracts
+  * the second time (in sec, mil) from the first (sec, mil).
+  */
+ #ifndef GETTIMEOFDAY
+ 
+ gettime(s, m)
+ 	long *s, *m;
+ {
+ 
+ 	(void) time(s);
+ 	*m = 0;
+ }
+ 
+ timesub(ds, dm, s, m)
+ 	long *ds, *dm, s, m;
+ {
+ 
+ 	*ds -= s;
+ }
+ 
+ #else
+ 
+ #include <sys/time.h>
+ 
+ gettime(s, m)
+ 	long *s, *m;
+ {
+ 	struct timeval now;
+ 
+ 	if (gettimeofday(&now, (struct timezone *)0))
+ 		perror("gettimeofday"), exit(1);
+ 	*s = now.tv_sec;
+ 	*m = now.tv_usec / 1000;
+ }
+ 
+ /*
+  * N.B.: we assume 0 <= m < 1000.
+  */
+ timesub(ds, dm, s, m)
+ 	long *ds, *dm, s, m;
+ {
+ 	register long s1 = *ds, m1 = *dm;
+ 
+ 	s1 -= s;
+ 	if ((m1 -= m) < 0) {
+ 		s1--;
+ 		m1 += 1000;
+ 	}
+ 	*ds = s1;
+ 	*dm = m1;
+ }
+ 
  #endif
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu

frank@sagan.UUCP (Frank Whaley) (10/18/85)

I've tried mailing this, but my uuxqt urps on the path to rer.

 * MACHINE	MICROPROCESSOR	OPERATING	COMPILER	DHRYSTONES/SEC.
 * TYPE				SYSTEM				NO REG	REGS
 * --------------------------	------------	-----------	---------------
 * IBM PC/XT	8088-4.77Mhz	VENIX/86 2.0	cc		 297	 324
 * Cosmos	68000-8Mhz	UniSoft		cc		 305	 322
 * IBM PC/XT	8086-4.54Mhz	PCDOS 3.1	Lattice 2.15	 373	  -  @
 * IBM PC/XT	8088-4.77Mhz	PCDOS 2.1	Lattice 2.15	 403	  -  @
 * ATT PC6300	8086-8Mhz	MSDOS 2.11	b16cc 2.0	 632	 684
 * Macintosh	68000-7.7Mhz	-		MegaMax C 2.0	 661	 709
 * IBM PC/AT	80286-6Mhz	PCDOS 3.0	CI-C86 2.1	 666	 684
 * Macintosh	68000-7.8Mhz 2M	Mac Rom		Mac C 32 bit int 694	 704
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Microsoft 3.0	 724	 781
 * ATT 3B2/300	MAC32-?Mhz	UNIX 5.0.2	cc		 735	 806
 * NEC PC9801F	8086-8Mhz	PCDOS 2.11	Lattice 2.15	 768	  -  @
 * ATT PC6300	8086-8Mhz	MSDOS 2.11	CI-C86 2.20M	 769	 769
 * Fast Mac	68000-7.7Mhz	-		MegaMax C 2.0	 839	 904 +
 * VAX 11/750	-		Unix 4.2bsd	cc		 862	 877
 * Macintosh	68000-7.8Mhz 2M	Mac Rom		Mac C 16 bit int 877	 909
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Microsoft 3.0	 724	 781
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Wizard 2.1	 877	 980
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Wizard 2.1	 877	 980
 * VAX 11/750	-		VMS		VAX-11 C 2.0	 958	1091
 * IBM PC/AT	80286-6Mhz	VENIX/86 2.1	cc		 961	1000
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Lattice 2.15	 980	  -  @
 * ATT PC7300	68010-10Mhz	UNIX 5.2	cc		1041	1111
 * IBM PC/AT	80286-6Mhz	PCDOS 3.1	Microsoft 3.0	1063	1086
 * Sun2/120	68010-10Mhz	Sun 4.2BSD	cc		1136	1219
 * PDP 11/70	-		UNIX 5.2	cc		1162	1250
 * IBM PC/AT	80286-7.5Mhz	VENIX/86 2.1	cc		1190	1315 *
 * IBM PC/AT	80286-6Mhz	PCDOS 3.1	Lattice 2.15	1250	  -  @
 * VAX 11/780	-		UNIX 5.2	cc		1515	1562
 * ATT 3B20	-		UNIX 5.2	cc		1515	1724
 * uVAX-II	-		?		?		1574	1582
 * Gould PN6005	-		UTX 1.1(4.2BSD)	cc		1675	1964
 * HP9000-500   B series CPU    HP-UX 4.02      cc		1724      -
 * Pyramid 90x  -		OSx 2.5		cc		3125    3125
 * SUN 3/75	68020-16.67Mhz	SUN 4.2 V3	cc		3333	3571
 * Amdahl 580	-		UTS 5.0 Rel 1.2	cc Ver. 1.5    23076   23076
 *
 *   * 15Mhz crystal substituted for original 12Mhz;
 *   @ vanilla Lattice compiler used with MicroPro standard library
 *   + This Macintosh was upgraded from 128K to 512K in such a way that
 *     the new 384K of memory is not slowed down by video generator accesses.
 *
 *	The important ones (to me):
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Microsoft 3.0	 819	 877
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Wizard 2.1	 877	 980
 * IBM PC/XT	8086-9.54Mhz	PCDOS 3.1	Lattice 2.15	 980	  -  @
-- 
frank
... Frank Whaley, MicroPro Product Development
{dual,hplabs,glacier,lll-crg}!well!micropro!sagan!frank

	"The heights by great men reached and kept,
	 were not attained by sudden flight.
	 But they, while their companions slept,
	 were toiling upward in the night."
			-Longfellow