Saturday, September 29, 2007

Erlang/Java Performance in Concurrency

I've been learning Erlang for 1 week now and i discover its a nice language for programming. This language is definitely different from C, C++ and Java.

In this post, i shall boldly compare the difference in runtimes for Erlang and Java w.r.t. concurrency.

In Erlang, I created a file ring.erl which contains the following code


-module(ring).
-export([start/2, for/3, loop/0]).

-ifndef(debug).
-define(TRACE(X), io:format("~p:~p ~p~n", [?MODULE, ?FILE, X])).
-else.
-define(TRACE(X), void).
-endif.

for(N, N, F) -> F();
for(I, N, F) -> F(),for(I+1, N,F).

%
% Create N processes and send a message M times
% to each process. Therefore, we should generate N * M
% messages.
%

loop() ->
receive
{msg, Pid} -> Pid, loop()
after 5000 ->
done
end.

start(N, M) ->
statistics(runtime),
statistics(wall_clock),
ring:for(1, N, fun() -> Pid = spawn(ring, loop, []), ring:for(1, M, fun() -> Pid ! {msg, Pid} end) end),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
io:format("Runtime:~p, Walltime:~p~n", [Time1, Time2]).


In Java, I used Netbeans 5.5.1 (JDK 1.5.0_12) to develop the following simple multi-threaded Java code:


package simplemultithread;

public class Main {

/** Creates a new instance of Main */
public Main() {
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
long startTime = System.currentTimeMillis();
if ( args.length != 2 ) {
System.err.println("usage: java Main <Number of threads> <Number of msg to send to each thread>");
System.exit(-1);
}
int numOfThreads = Integer.parseInt(args[0]);
final int numOfMsgsPerThread = Integer.parseInt(args[1]);
Thread threads[] = new Thread[numOfThreads];

for( int i = 0; i < numOfThreads; i++ ) {
threads[i] = new Thread() {
private int msgsToProcess = numOfMsgsPerThread;
public void run() {
for( int i = 0, j = 0; i < msgsToProcess; i++ ) {
// do something simple
j++;
}
}
};
try { threads[i].join();} catch (InterruptedException ie) {}
}
for( int i = 0; i < numOfThreads; i++ ) {
threads[i].start();
}
long endTime = System.currentTimeMillis();
System.out.println("Total time:" + (endTime - startTime)/1000.00 + "seconds");
}

}


And the performance difference is quite remarkable after comparing the runtimes of both programs which perform almost the same thing i.e. start N processes/threads and each process executes its action M-times.

In my tests, i used a Compaq notebook Intel-M 2.4 Ghz with 512 MB RAM running SUSE Linux 9.3 Professional Operating System.

The figure on the left is the runtime, in milliseconds, of the Erlang code above and that on the right is that of the Java code. From the figures, you can see that Erlang runs better than Java in order of approximately 2-3 times!

How does Erlang do it? The best way to understand it is to see this article.


No comments: