Sunday, November 13, 2005

Benchmark comparing Java, C++, Delphi, PHP and Python

I created a little benchmark and was surprised to learn that Java outperformed C++. I am a Delphi developer and look for alternatives, and Java seems much more attractive than both C++ and C#.

Here are the results (I used optimizations where available):

Language / Execution time (ms.) -> Less is better!

Java 599
C++ 6979
Delphi 9708
Python 55906
PHP 171172

Language / Speed (%) -> Less is worse!

Java 100
C++ 8,6
Delphi 6,1
Python 1,1
PHP 0,35

And here is the source code:

C++

#include
#include

using namespace std;

class Robot
{
private:
string name;
public:
void SetName(string name);
string GetName();
};

void Robot::SetName(string name)
{
this->name = name;
}

string Robot::GetName()
{
return this->name;
}

int main()
{
int start = GetTickCount();
const int loops = 256;
const string name = "Terminator";

Robot** robots = new Robot*[loops];
int numInstances = 0;

for(int x=0; x {
for(int y=0; y {
for(int z=0; z {
robots[x] = new Robot();
robots[x]->SetName(name);

if(robots[x]->GetName() == name)
numInstances++;

delete robots[x];
}
}
}

delete [] robots;
int stop = GetTickCount();
printf("Created a total of %d instances.\n", numInstances);
printf("Took %d ms.\n", stop - start);

return 0;
}

Delphi

program Benchmark;

{$APPTYPE CONSOLE}

uses
SysUtils, Windows;

type
TRobot = class(TObject)
private
FName: String;
procedure SetName(Value: String);
function GetName: String;
public
property Name: String read GetName write SetName;
end;

{ TRobot }

function TRobot.GetName: String;
begin
Result := FName;
end;

procedure TRobot.SetName(Value: String);
begin
FName := Value;
end;

const
Loops = 256;
Name = 'Terminator';
var
X, Y, Z: Integer;
Robots: array of TRobot;
Start, Stop: Integer;
NumInstances: Integer;
begin
Start := GetTickCount;

NumInstances := 0;
SetLength(Robots, Loops);

for X := 0 to Loops - 1 do begin
for Y := 0 to Loops - 1 do begin
for Z := 0 to Loops - 1 do begin
Robots[X] := TRobot.Create;
Robots[X].Name := Name;

if Robots[X].Name = Name then
Inc(NumInstances);

Robots[X].Free;
end;
end;
end;

Stop := GetTickCount;
WriteLn(Format('Created a total of %d instances.', [NumInstances]));
WriteLn(Format('Took %d ms.', [Stop - Start]));

ReadLn;
end.

Java

class Robot
{
private String name;

public void setName(String name)
{
this.name = name;
}

public String getName()
{
return this.name;
}
}

public class Main
{
public static void main(String[] args)
{
long start = System.currentTimeMillis();

final int loops = 256;
final String name = "Terminator";
Robot[] robots = new Robot[loops];
long numInstances = 0;

for(int x=0; x {
for(int y=0; y {
for(int z=0; z {
robots[x] = new Robot();
robots[x].setName(name);

if(robots[x].getName().equals(name))
numInstances++;
}
}
}

long stop = System.currentTimeMillis();
System.out.printf("Created a total of %d instances.\n", numInstances);
System.out.printf("Took %d ms.\n", stop - start);
}
}

PHP

class Robot
{
var $name;

function SetName($name)
{
$this->name = $name;
}

function GetName()
{
return $this->name;
}
}

$start = microtime(true);

$loops = 256;
$name = "Terminator";

$robots = array();
array_pad($robots, loops, null);

$num_instances = 0;
for($x=0; $x<$loops; $x++)
{
for($y=0; $y<$loops; $y++)
{
for($z=0; $z<$loops; $z++)
{
$robots[$x] = new Robot();
$robots[$x]->SetName($name);

if($robots[$x]->GetName() == $name)
$num_instances++;
}
}
}

$stop = microtime(true);
printf("Created a total of %d instances.\n", $num_instances);
printf("Took %d ms.\n", ($stop - $start) * 1000);
?>

Python

import time

class Robot:
def __init__(self):
self.name = ''

def set_name(self, value):
self.name = value

def get_name(self):
return self.name

start = time.time()
loops = 256
name = "Terminator"

robots = []
for x in xrange(loops):
robots.append(None)

num_instances = 0

for x in xrange(loops):
for y in xrange(loops):
for z in xrange(loops):
robots[x] = Robot()
robots[x].set_name(name)

if robots[x].get_name() == name:
num_instances += 1


stop = time.time()
print "Created a total of %d instances." % (num_instances)
print "Took %d ms." % ((stop - start) * 1000)

Saturday, November 12, 2005

This is a simple step by step tutorial that explains how to setup Eclipse on Windows for SDLJava:
  1. Download sdljava-0.9.1-win32-bin.zip and optionally sdljava-0.9.1-src.zip (It contains the source code for the samples, very handy).
  2. Extract to any directory (e.g. C:\Java\sdljava-0.9.1).
  3. Click Start -> Settings -> Control Panel -> System -> Advanced -> Environment Variables and append C:\Java\sdljava-0.9.1\lib to the Path system variable.
  4. Go to C:\Java\sdljava-0.9.1\bin and execute testsprite.bat - If it works, congratulations, 75% done.
  5. Open Eclipse, create a new project, add a source file to it and paste the following into it:
  6. import sdljava.*;
    import sdljava.video.*;

    class HelloSDL {
    public static void main(String[] args) {
    final String caption = "Hello, SDL!";
    System.out.println(caption);

    try {
    SDLMain.init(SDLMain.SDL_INIT_VIDEO);
    SDLVideo.wmSetCaption(caption, caption);
    SDLSurface screen = SDLVideo.setVideoMode(640, 480, 24, 0);
    java.lang.Thread.sleep(2500);

    } catch(Exception e) {
    e.printStackTrace();
    } finally {
    SDLMain.quit();
    }
    }

    }

  7. Right click the source file and choose Run As ... Run.
  8. If there isn't already an entry below "Java Application", create one. Ensure that the main class is set to "HelloSDL".
  9. Switch to the Arguments tab and add the following to VM arguments: -Djava.library.path=C:\Java\sdljava-0.9.1\lib
  10. Open the project properties, select Java Build Path -> Libraries and click on Add external JARs, then choose C:\Java\sdljava-0.9.1\lib\sdljava.jar and click Open.
  11. Run the project. If it works, that's all there is to it!
Make sure you consult the SDL documentation and the sample source code that ships with SDLJava (testsrc\testsuite).