Showing posts with label notes. Show all posts
Showing posts with label notes. Show all posts

Monday, March 08, 2010

Reading Notes #3: Ring Benchmark

I have been working my way through Joe Armstrong's Programming in Erlang. One of the exercises in chapter 8 is to write a "ring benchmark" in Erlang and any other language, compare the results and publish them.

Write a ring benchmark. Create N processes in a ring. Send a message round the ring M times so that a total of N * M messages get sent. Time how long this takes for different values of N and M. Write a similar program in some other programming language you are familiar with. Compare the results. Write a blog, and publish the results on the Internet!

Here are my benchmarks written in Erlang and Python respectively. I have presumed that the author meant sending messages synchronously; i.e. a message has to go around the whole ring before the next can be sent.

The Erlang version was easy to write. After all the language is designed to use a processes and messages paradigm of programming. Here is the source code:

I wrote the "other programming language" version in Python. The benchmark code makes use of Python's multiprocessing module (available in version 2.6 and above). Since I couldn't find any Erlang-style way to directly send a message to a process I chose to use a set of Queue objects to accomplish message passing. Each process has access to two queues - an "in" queue to receive messages and an "out" queue to relay them to the next process in the ring. Each process' "out" queue serves as the "in" for the next. After constructing N - 1 processes, a "plug" process is created to complete the process ring.

I am not entirely convinced that Python's processes are the equivalent of Erlang ones. Certainly threads are not the answer given their use of shared memory. Perhaps the difficulty in creating lightweight, shared-nothing processes in other languages is what the author wanted to illustrate using the example.

The results are shown below. The program was executed on a machine with a dual core Pentium, 2GB memory and running Ubuntu Jaunty.

Please note that:
  • I could not increase the number of Python processes to the order of 1000 (10^3). When I tried to do this the program crashed with a number of errors.
  • I got a curious QueueFeederThread exception when I executed the process for N = 100, M = 10000.

N M N * M (Wall) Time in seconds
Erlang Python
10 10 10^2 0.0 0.0732
10 100 10^3 0.003 0.1795
100 100 10^4 0.036 2.3976
100 1000 10^5 0.242 12.2252
1000 1000 10^6 1.877 -
1000 10000 10^7 18.593 -
10000 10000 10^8 197.477 -

Tuesday, November 17, 2009

Reading Notes #2: Passing functions as arguments to higher order functions

Does Erlang allow you to pass functions (not "funs" or anonymous functions) as arguments to higher order functions? I was under the impression that it doesn't. To find out I tweeted a question about the same. After looking at the answers I decided to rephrase the question with the help of a concrete example. Here it goes:

Step 1: Define a function add_one in a module named test.

Step 2: Start the erlang shell and try to use this function.

As you can see I have tried three different combinations. Line #3 shows a call to the higher order function lists:map passing in the qualified name of the add_one function as first argument. The shell throws an error.

In Line #4 I wrap test:add_one inside a fun and it works.

In Line #5 I replicate the code of add_one inside an anonymous fun and everything works fine.

Contrast this with say, Python.

Definition:

Usage:

Now I'll repeat the question: Does Erlang allow you to pass functions (not "funs" or anonymous functions) as arguments to higher order functions? Or am I missing something?

Please share your thoughts in the comments.

Update #1:
Got an answer. There is a way to do it. It still involves using the fun keyword.
Update #2:
Got another answer which does *not* use fun. The syntax is just a little different. Thanks to Justin Sheehy.

Wednesday, October 14, 2009

Reading Notes #1

I have been reading Joe Armstrong's paper "Making reliable distributed systems in the presence of software errors" and making notes as I go. In chapter 3 the author gives examples of how Erlang handles higher order functions. One of them is a "generator" function.

Line 1 defines an Adder that returns another function with X bound to the input to Adder. In line 2 we create a specific adder - in this case a function that adds 10 to its input. I think line 3 was meant to show how the specific adder created in line 2 could be invoked. If Adder10 were to be called with 5 as argument it would return 15. Instead Adder is invoked again and the result shown is not correct as Adder(10) would return a generator, not 15. I think the snippet can be modified thus: