Haskell is 4.2x as good as Erlang at lightweight concurrency. Give it some love.
shootout.alioth.debian.org
shootout.alioth.debian.org
Kidding aside, I think the fact that Erlang got thrown into the production ring so early is perhaps a hindrance to its growth in some ways. They can't just go fiddling with the language at this point without some serious breakage, whereas newer languages like Scala and Clojure would probably not create major problems should they go through a few incompatible versions. Yes, people are using them in production, but not for things like phone switches!
It's definitely an interesting language; but I would see it as more competitive with C, C++ or Java as a language for building high reliability components.
It created layouts that performed over 10% faster than the best hand-tuned layouts at the time. My understanding is that it was for the DoD.
I say this as someone who would like to see that happen (though I have no resources to do it myself). But until that happens, Erlang has a niche that Haskell can't fill; you can toss robust, multi-machine-scalable servers together in Erlang way faster than you can put them together in Haskell. It's not something intrinsic to the language, it's just Haskell doesn't have the libraries.
Conventional Prolog wasn't an option* , because the backtracking inherent in its execution model leads to significant variance for worst-case timing for individual operations. The same problem can happen with lazy evaluation, for both time and space - while the sophisticated compiler optimizations can allow for some really remarkable amortized performance, individual worst-case measurements can still have some serious outliers.
* Though Erlang was prototyped in SICStus Prolog.
With lazy evaluation, forcing a thunk for a seemingly minor operation can trigger a burst of postponed work. This can be a problem if it means a sudden drop in a game's framerate, for example, much like non-incremental garbage collectors' pauses have made people wary of using GC. Similarly, a JITting compiler can do more elaborate optimizations if it can afford to stall the program perceptibly while performing them, but that would disqualify the compiler for many real-world uses.
Real-time operation can impact performance, much like implementing full transactions slows down databases. Still, it's a fairly significant feature in its own right, and a language that does concurrency faster overall, but cannot prevent occasional erratic timing, is aiming for a different target than those (e.g. Erlang) that have such guarantees. It's not unusual for a program that juggles tens of thousands of connections to need to respond to them promptly, for example. Concurrency isn't just about performance.
(Also, that's why the Erlang movie has that "Declarative real-time programming NOW!" banner in the background. :) )
Something to keep in mind.
If your "app" is a toy microbenchmark with an under-specified benchmarking methodology, then sure. You could also make your "app" 360x faster by switching to a userspace thread implementation.
I am sure C would do better with a proper userspace thread library, but nobody has submitted such a program to the shootout yet. "If it's so easy..."
(Actually, not true, when I worked for $LARGE_ADVERTISING_COMPANY, we checked the state of the session in the database for every request. This put an enormous load on the database, and made every page load take at least two seconds waiting for locks. No, I did not design any part of this system, nor was I allowed to fix it; so it doesn't count :)
Programs may use kernel threads, lightweight threads; but coroutines, cooperative threads and other programs with custom schedulers will be listed as interesting alternative implementations.
However, the Haskell docs for Control.Concurrent note that in Haskell,
Concurrency is "lightweight", which means that both thread creation and context switching overheads are extremely low. Scheduling of Haskell threads is done internally in the Haskell runtime system, and doesn't make use of any operating system-supplied thread packages.
Which makes the comparison with a C implementation that uses kernel threads pretty unfair: presumably a C implementation that uses green threads / fibers would be much more competitive with the Haskell implementation. Comparing apples to oranges isn't very informative.
As an aside, choosing a language based on how fast its green thread implementation happens to be at passing tokens around a ring is utterly silly.
Edit: The benchmark in question does just this, with 5 cores. So while the docs you cut-n-pasted are technically accurate, they do not apply to this particular run of this particular benchmark.
the threads are scheduled amongst the available CPU cores.
Actually, the per-CPU idle stats suggest that the Haskell program ran entirely on a single CPU, so it wasn't actually utilizing all 4 cores anyway.
Partly there's an issue here that the priority for Erlang has always been more multi-box distributed systems rather thaan single-box concurrency, and partly there's an issue that Erlang's not-really-open-source nature seems to hold back progress in fixing issues like this. And, partly there's the fact that the Erlang core team doesn't really care at all about micro-benchmarks like this.
> 0% 0% 0% 100%
This was a Quad Core CPU, so my first impulse is to ask, does that mean it was running on only one core?
Yeah, when I looked at the definition of the problem, it sort of made sense.
Le sigh ... dammit, I should give Haskell more of my attention.
I just hate camel casing and type errors :( And if I'm going to procrastinate about writing For Reals code in a language, various lisps have that covered already.
Although, I'm writing a For Reals app in Ruby (w/merb) at the moment, and it's turning into a bit of an uggo. Maybe I'll procrastinate about finishing it, and give Haskell another go.
Also, Haskell is just a really, really difficult language, and it's hard to pass accurate judgment until you've mastered it. When I first started studying Lisp, it took about six weeks of intense study before I really felt like I grokked the language. Coming into Haskell with my existing Lisp background, it took me a year to feel the same way.
I did give The Haskell School of Expression a good whirl -- heh, I brought it down to south america with me, and hacked through a little of it each morning for a couple of months, swinging in a hammock and listening to waves crash and deciding that the water was probably still too cold to go out.
But although I understood what I was reading and understood what the code I had written did ... grok I did not.
I couldn't think creatively in Haskell AT. ALL.
Nonetheless, your comment heartens me. Please reassure me further: are you a person who has ever written or attempted to write a non-trivial mathematic proof?
Err, I mean, my problem. Le double sigh.
What is particularly interesting is that Haskell uses only one CPU to beat Java which is using four.
That's conceptual more of an apples-to-apples comparison.