Nobody can predict the future, but I’m going to make a few informed guesses.

Let’s suppose Intel is right: let’s suppose that the Keifer project succeeds. If this happens, then 32 core processors will appear on the market as soon as 2009/2010.

This comes as no surprise; Sun already ships the Niagara with 8 cores running 4 hyperthreads per core (which is equivalent to 32 cores).

This is a development that makes Erlang programmers very happy. They have been waiting 20 years for this to happen, and now it’s payback time.

Here’s the good news for Erlang programmers:

Your Erlang program should just run N times faster on an N core processor

Is this true?

Almost. It’s early still, but we’re optimistic (Wildly optimistic; I haven’t seen this kind of optimism for the last 20 years!).

Sometimes we have to tweak our programs a bit—when I generated some Erlang documentation on a Sun Niagara (with 32 equivalent cores), I had to make a one line tweak to my program (I changed a map to pmap—sorry, I’m getting technical here. pmap is just “parallel map”).

The program (which generates 63 documents from wiki markup) ran 7 times faster. Not 32, I’ll grant you, but significantly faster. (later work makes us think we hit an I/O bottleneck writing to the disk here, so unless the disk I/O gets parallelized we’ll be stuck at 7 here :-)

At Ericsson, where I work and where Erlang was developed, we’re moving some applications onto 4 core processors—and guess what? After a little tweaking they run almost 4 times faster. We can’t wait for the 80 core processes that Intel has in the labs …

Why do our programs just run faster? It’s all about mutable state and concurrency

Mutable State and Concurrency

Back in the old days (20 odd years ago) there were two models of concurrent:

  • Shared state concurrency
  • Message passing concurrency

Now the whole world went one way (towards shared state), and we went the other.

Very few languages have followed the “Message passing concurrency road”; some others that did so were Oz and Occam.

In message passing concurrency, we say that there is no shared state. All computations are done in processes and the ONLY way to exchange data is through asynchronous message passing.

So why is this good?

Shared state concurrency involves the idea of “mutable state” (literally memory which can be changed). All languages like C, Java, C++, etc., have the notion that there is this stuff called “memory” and we can change it.

This is fine as long as you only have ONE process doing the changing.

But if you have multiple processes sharing and modifying the SAME memory this is a recipe for disaster—madness lies here.

To protect against simultaneous modification of shared memory, we need a locking mechanism. Call this a mutex or a synchronised method or what you will, it’s still a lock.

If programs crash in the critical region (i.e., at the time when they hold the lock) disaster results. All the other programs don’t know what to do.

How do programmers fix these problems? They don’t. They pray. On a unicore processor their program might just work, but on a multicore—disaster.

There are various solutions to this (transaction memories is probably the best), but these are at best kludges—and at worse, nightmares.

Erlang Has No Mutable Data Structures

(Not quite true, but true enough)

No Mutable Data Structures = No Locks

No Mutable Data Structures = Easy to parallelize

How do we do the parallelization? Easy, the programmer breaks up the solution of the problem into a number of parallel processes.

This style of programming has it’s own terminology—it’s called

... roll the drums: ....

Concurrency Oriented Programming

Erlang doesn’t do objects—it has its own metaphor.

Objects are out. Concurrency is in.

The world IS concurrent. It IS parallel. Things happen all over the place at the same time. I could not drive my car on the highway if I did not intuitively understand the notion of concurrency; pure message-passing concurrency is what we do all the time.

Imagine a group of people. They have no shared state.

I have my private memory (in my head) and you have yours. It is NOT shared. We communicate by passing messages (sound and light waves). We update or private state based on the reception of these messages.

That’s Concurrency Oriented Programming in a nutshell.

As for hiding mutable state in an object: it is exactly this property that make parallelization an almost impossibly difficult problem.

Does it work?

Yes. Erlang is used all over the world in high-tech projects where reliability counts. The Erlang flagship project (built by Ericsson, the Swedish telecom company) is the AXD301. This has over 2 million lines of Erlang.

The AXD301 has achieved a NINE nines reliability (yes, you read that right, 99.9999999%). Let’s put this in context: 5 nines is reckoned to be good (5.2 minutes of downtime/year). 7 nines almost unachievable ... but we did 9.

Why is this? No shared state, plus a sophisticated error recovery model. You can read all the details in my PhD thesis

Who Uses Erlang?

  • People “in the know”
  • Startups
  • Ericsson
  • wings, a 3d modeling program http://www.wings3d.com/
  • ejabberd, an instant messaging server for jabber/XMPP
  • tsung, a multi-protocol distributed load testing tool
  • yaws, a very-high performance web server
  • Thousands of (“I wish I could do this in my day job”) hobby hackers.

Is Erlang Difficult?

No—but it’s different.

Erlang does not have “A C-like syntax to make it easy to learn.” It is not “Object Oriented,” it does not have “Mutable state,” and it’s a “Functional programming Language.”

This is all scary stuff—and at first sight, off-putting to the new user. The funny thing is that it’s really a very small and simple language.

You might be wondering what Erlang code looks like. Erlang makes heavy use of a pattern matching syntax; here’s a small example of Erlang code (from the new Erlang book):

-module(geometry).
-export([area/1]).
area({rectangle, Width, Ht}) -> Width * Ht;
area({square, X}) -> X * X;
area({circle, R}) -> 3.14159 * R * R.

Now we’ll compile and run it in the Erlang shell:

1> c(geometry).
{ok,geometry}
2> geometry:area({rectangle, 10, 5}).
50
3> geometry:area({circle, 1.4}).
6.15752

Pretty easy… Here’s some Java that does something similar:

abstract class Shape {
    abstract double area();
}
class Circle extends Shape {
    final double radius;
    Circle(double radius) { this.radius = radius; }
    double area() { return Math.PI * radius*radius; }
}
class Rectangle extends Shape {
    final double ht;
    final double width;
    Rectangle(double width, double height) {
        this.ht = height;
      this.width = width;
    }
    double area() { return width * ht; }
}
class Square extends Shape {
    final double side;
    Square(double side) {
      this.side = side;
    }
    double area() { return side * side; }
}

Where Do I Download Erlang?

You can download Erlang from erlang.org

How do I learn more about Erlang?

Well, I am just finishing up Programming Erlang: Software for a Concurrent World (Pragmatic Bookshelf, US$36.95, 978-1-934356-00-5)

This is a tutorial introduction to Erlang. It covers the entire language and includes full source code for a number of demo applications. These include:

  • An irc/chat like system
  • A SHOUTcast server for streaming media
  • An implementation of map-reduce which is used to build a full-text indexing system

Blogs

There’s a lot of activity in the blogsphere; go to Google search and search for Erlang blogs. Also, here are some articles you might enjoy:

Web documentation

Now go and look in this directory. You’ll find 50-odd PDF files here. I’ve chosen a few of these for you to look at:

Each one of these represents a book that is just waiting to be written :-)

Have a good read.

Copyright © 2007 Joe Armstrong

<< The Spirit of the Tool | Designing Learning >>