Newsgroups: comp.lang.smalltalk
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!oitnews.harvard.edu!newsfeed.rice.edu!bcm.tmc.edu!cs.utexas.edu!utnut!torn!nott!cunews!dbuck
From: dbuck@superior.carleton.ca (Dave Buck)
Subject: Re: Smalltalk vs C vs C++ benchmark results
X-Nntp-Posting-Host: superior.carleton.ca
Message-ID: <DErLqw.AHA@cunews.carleton.ca>
Sender: news@cunews.carleton.ca (News Administrator)
Organization: Carleton University, Ottawa, Canada
References: <DEDsF1.3I8@cunews.carleton.ca>
Date: Mon, 11 Sep 1995 23:40:08 GMT
Lines: 743

Here's the source code for the benchmarks I posted earlier.  Please
keep in mind that I'm trying to test the speed of operations we'd need
to perform frequently in a typical application.  The point is not to
see how clever the compiler can be at opimizing away poorly written
code.  I'm not interested in complaints that I'm using longs instead
of integers.  I need to use longs.  A value from -16384 to +16383
isn't sufficient.  Also, I've used pointers to all objects.  This
corresponds to a realistic way to deal with real-world objects.

The Smalltalk code was written for VisualWorks 2.0.  The C code was
written for Borland C++.  The test system was Windows 3.1.  Similar
tests were made under OS/2 using the IBM CSet++ compiler.  The only
differences in the code were:
	 - the call in C and C++ to capture the time
	 - the number of iterations was increased for all tests to
             account for a faster processor.

Without any further ado, here's the code:

Object subclass: #SimpleHanoi
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Speed tests'!


!SimpleHanoi methodsFor: 'processing'!

hanoi
	"SimpleHanoi new hanoi"
	^(Time millisecondsToRun:
		[self move: 22 from: 1 to: 2 temp: 3]) / 1000.0!

move: numberOfDisks from: source to: dest temp: temp
	numberOfDisks == 1 ifTrue: [^self].
	self
		move: numberOfDisks-1 from: source to: temp temp: dest;
		move: numberOfDisks-1 from: temp to: dest temp: source! !

Object subclass: #SpeedTester
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Speed tests'!


!SpeedTester methodsFor: 'tests'!

allocSpeedTest
	"SpeedTester new allocSpeedTest"
	ObjectMemory doOrFinishIncrementalGC.
	^Time millisecondsToRun: [
		100000 timesRepeat: [
			Array
				new:10;
				new:10;
				new:10;
				new:10;
				new:10;
				new:10;
				new:10;
				new:10;
				new:10;
				new:10].
	ObjectMemory doOrFinishIncrementalGC]!

arrayWriteSpeedTest
	| array junk |
	"SpeedTester new arrayWriteSpeedTest"
	junk := Object new.
	array := Array new: 10.
	^Time millisecondsToRun: [
		1000000 timesRepeat: [
			array
				at: 1 put: junk;
				at: 2 put: junk;
				at: 3 put: junk;
				at: 4 put: junk;
				at: 5 put: junk;
				at: 6 put: junk;
				at: 7 put: junk;
				at: 8 put: junk;
				at: 9 put: junk;
				at: 10 put: junk]]!

dictionaryWriteSpeedTest
	| dict junk key1 key2 key3 key4 key5 key6 key7 key8 key9 key10 |
	"SpeedTester new dictionaryWriteSpeedTest"
	junk := Object new.
	key1 := Object new.
	key2 := Object new.
	key3 := Object new.
	key4 := Object new.
	key5 := Object new.
	key6 := Object new.
	key7 := Object new.
	key8 := Object new.
	key9 := Object new.
	key10 := Object new.

	^Time millisecondsToRun: [
		10000 timesRepeat: [
			dict := IdentityDictionary new: 20.
			dict
				at: key1 put: junk;
				at: key2 put: junk;
				at: key3 put: junk;
				at: key4 put: junk;
				at: key5 put: junk;
				at: key6 put: junk;
				at: key7 put: junk;
				at: key8 put: junk;
				at: key9 put: junk;
				at: key10 put: junk]]!

floatMathSpeedTest
	"SpeedTester new floatMathSpeedTest"
	| a b c d e |
	a := 87.0.
	b := 53.0.
	c := -87.0.
	d := 42461.0.
	e := 5.0.
	^Time millisecondsToRun: [
		300000 timesRepeat: [
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d]]!

integerMathSpeedTest
	"SpeedTester new integerMathSpeedTest"
	| a b c d e |
	a := 87.
	b := 53.
	c := -87.
	d := 42461.
	e := 5.
	^Time millisecondsToRun: [
		300000 timesRepeat: [
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d.
			e := (e * a + b) * c + d]]!

orderedCollectionIterateSpeedTest
	| oc junk |
	"SpeedTester new orderedCollectionIterateSpeedTest"
	junk := Object new.
	oc := OrderedCollection new: 20.
	oc
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk;
		add: junk.

	^Time millisecondsToRun: [
		100000 timesRepeat: [
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ].
			oc do: [:element | ]]]!

orderedCollectionWriteSpeedTest
	| oc junk |
	"SpeedTester new orderedCollectionWriteSpeedTest"
	junk := Object new.

	^Time millisecondsToRun: [
		100000 timesRepeat: [
			oc := OrderedCollection new: 20.
			oc
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk;
				addLast: junk]]!

stringCompareSpeedTest
	"SpeedTester new stringCompareSpeedTest"
	^Time millisecondsToRun: [
		100000 timesRepeat: [
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings'.
			'this is a test of a string compare of two long strings'
				trueCompare: 'this is a test of a string compare of two long strings']]! !


--------------  C Code Follows -------------------

/* Alloc.c */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>

unsigned long Begin_Time, End_Time;

void main(int argc, char **argv)
	{
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		free (malloc(10));
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

/* Array.c */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>

unsigned long Begin_Time, End_Time;

void main(int argc, char **argv)
	{
	long i;
	long array[10];

	Begin_Time = GetCurrentTime();
	for (i=0; i<1000000L; i++) {
		array[0] = 0L;
		array[1] = 1L;
		array[2] = 2L;
		array[3] = 3L;
		array[4] = 4L;
		array[5] = 5L;
		array[6] = 6L;
		array[7] = 7L;
		array[8] = 8L;
		array[9] = 9L;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

/* floatmth.c */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>

unsigned long Begin_Time, End_Time;

long Glob;

void main(int argc, char **argv)
	{
	long i;
	float a, b, c, d, e;
	e = 5.0;
	a = 87.0;
	b = 53.0;
	c = -87.0;
	d = 42461.0;

	Begin_Time = GetCurrentTime();
	for (i=0; i<300000L; i++) {
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	Glob = e;
	}

/* hanoi.c */
#include <stdio.h>
#include <time.h>
#include <windows.h>

#define NUM_DISKS 22

unsigned long Begin_Time, End_Time;

void hanoi(int original, int destination, int free, int number_of_disks)
	{
	if (number_of_disks == 1)
		return;
	hanoi(original, free, destination, number_of_disks - 1);
	hanoi(free, destination, original, number_of_disks - 1);
	}

void main(int argc, char **argv)
	{
	Begin_Time = GetCurrentTime();
	hanoi(1, 2, 3, NUM_DISKS);
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

/* intmath.c */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>

unsigned long Begin_Time, End_Time;

long Glob;

void main(int argc, char **argv)
	{
	long i;
	long a, b, c, d, e;
	e = 5;
	a = 87;
	b = 53;
	c = -87;
	d = 42461L;

	Begin_Time = GetCurrentTime();
	for (i=0; i<300000L; i++) {
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		e = (e * a + b) * c + d;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	Glob = e;
	}

/* strcmp.h */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>

unsigned long Begin_Time, End_Time;


void main(int argc, char **argv)
	{
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		strcmp ("this is a test of a string compare of two long strings",
			 "this is a test of a string compare of two long strings");
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

---------------  C++ Code --------------------
/* alloc.cpp */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>

unsigned long Begin_Time, End_Time;

class MyClass {
	public:
		long arr[10];
	};

void main(int, char **)
	{
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		delete (new MyClass);
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

/* array.cpp */
#include <stdio.h>
#include <windows.h>
#include "rw\collect.h"
#include "rw\tpvector.h"

unsigned long Begin_Time, End_Time;

class MyClass : public RWCollectable {
	RWDECLARE_COLLECTABLE(MyClass)
	};
	RWDEFINE_COLLECTABLE(MyClass, 1)


void TimeArray()
	{
	MyClass *testObject = new MyClass();
	RWTPtrVector<MyClass> *array = new RWTPtrVector<MyClass>(10);
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<1000000L; i++) {
		(*array)[0] = testObject;
		(*array)[1] = testObject;
		(*array)[2] = testObject;
		(*array)[3] = testObject;
		(*array)[4] = testObject;
		(*array)[5] = testObject;
		(*array)[6] = testObject;
		(*array)[7] = testObject;
		(*array)[8] = testObject;
		(*array)[9] = testObject;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	delete testObject;
	delete array;
	}

void main(int , char **)
	{
	TimeArray();
	}

/* dict.cpp */
#include <stdio.h>
#include <windows.h>
#include "rw\collect.h"
#include "rw\idendict.h"

unsigned long Begin_Time, End_Time;

class MyClass : public RWCollectable {
	RWDECLARE_COLLECTABLE(MyClass)
	};
	RWDEFINE_COLLECTABLE(MyClass, 1)

void TimeDictionary()
	{
	MyClass *testObject = new MyClass();
	MyClass *key1 = new MyClass();
	MyClass *key2 = new MyClass();
	MyClass *key3 = new MyClass();
	MyClass *key4 = new MyClass();
	MyClass *key5 = new MyClass();
	MyClass *key6 = new MyClass();
	MyClass *key7 = new MyClass();
	MyClass *key8 = new MyClass();
	MyClass *key9 = new MyClass();
	MyClass *key10 = new MyClass();
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<10000L; i++) {
		RWIdentityDictionary *dict = new RWIdentityDictionary(20);
		dict->insertKeyAndValue (key1, testObject);
		dict->insertKeyAndValue (key2, testObject);
		dict->insertKeyAndValue (key3, testObject);
		dict->insertKeyAndValue (key4, testObject);
		dict->insertKeyAndValue (key5, testObject);
		dict->insertKeyAndValue (key6, testObject);
		dict->insertKeyAndValue (key7, testObject);
		dict->insertKeyAndValue (key8, testObject);
		dict->insertKeyAndValue (key9, testObject);
		dict->insertKeyAndValue (key10, testObject);
		delete dict;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	delete testObject;
	}
void main(int , char **)
	{
	TimeDictionary();
	}

/* hanoi.cpp */
#include <stdio.h>
#include <time.h>
#include <windows.h>

#define NUM_DISKS 22

unsigned long Begin_Time, End_Time;

class Hanoi {
	public:
		/*virtual*/ void hanoi(int original, int destination, int free, int number_of_disks);
	};

void Hanoi::hanoi(int original, int destination, int free, int number_of_disks)
	{
	if (number_of_disks == 1)
		return;

	hanoi(original, free, destination, number_of_disks - 1);
	hanoi(free, destination, original, number_of_disks - 1);
	}

void main(int, char **)
	{
	Hanoi hanoi;

	Begin_Time = GetCurrentTime();
	hanoi.hanoi(1, 2, 3, NUM_DISKS);
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	}

/* order.cpp */
#include <stdio.h>
#include <windows.h>
#include "rw\collect.h"
#include "rw\ordcltn.h"

unsigned long Begin_Time, End_Time;

class MyClass : public RWCollectable {
	RWDECLARE_COLLECTABLE(MyClass)
	};
	RWDEFINE_COLLECTABLE(MyClass, 1)


void TimeOrderedCollection()
	{
	MyClass *testObject = new MyClass();
	long i;

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		RWOrdered *oc = new RWOrdered(20);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		oc->insert (testObject);
		delete oc;
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	delete testObject;
	}

void main(int , char **)
	{
	TimeOrderedCollection();
	}

/* ordtiter.cpp */
#include <stdio.h>
#include <windows.h>
#include "rw\collect.h"
#include "rw\ordcltn.h"

unsigned long Begin_Time, End_Time;

class MyClass : public RWCollectable {
	RWDECLARE_COLLECTABLE(MyClass)
	};
	RWDEFINE_COLLECTABLE(MyClass, 1)


void TimeOrderedCollection()
	{
	MyClass *testObject = new MyClass();
	long i;

	RWOrdered *oc = new RWOrdered(20);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);
	oc->insert (testObject);

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		RWOrderedIterator iter1(*oc);
		while (iter1() != NULL);
		RWOrderedIterator iter2(*oc);
		while (iter2() != NULL);
		RWOrderedIterator iter3(*oc);
		while (iter3() != NULL);
		RWOrderedIterator iter4(*oc);
		while (iter4() != NULL);
		RWOrderedIterator iter5(*oc);
		while (iter5() != NULL);
		RWOrderedIterator iter6(*oc);
		while (iter6() != NULL);
		RWOrderedIterator iter7(*oc);
		while (iter7() != NULL);
		RWOrderedIterator iter8(*oc);
		while (iter8() != NULL);
		RWOrderedIterator iter9(*oc);
		while (iter9() != NULL);
		RWOrderedIterator iter10(*oc);
		while (iter10() != NULL);
		}
	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	delete testObject;
	delete oc;
	}

void main(int , char **)
	{
	TimeOrderedCollection();
	}

/* strcmp.cpp */
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include "rw\cstring.h"

unsigned long Begin_Time, End_Time;

void main(int argc, char **argv)
	{
	long i;

	RWCString *s1 = new RWCString("this is a test of a string compare of two long strings");
	RWCString *s2 = new RWCString("this is a test of a string compare of two long strings");

	Begin_Time = GetCurrentTime();
	for (i=0; i<100000L; i++) {
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		s1->compareTo(*s2);
		}

	End_Time = GetCurrentTime();
	printf ("%ld %ld %f\n", Begin_Time, End_Time, (End_Time - Begin_Time)/1000.0);
	delete s1;
	delete s2;
	}
