Where are the dynamic AND concurrent languages?
Saturday, September 29th, 2007There are two programming buzz areas that get a lot of thought mileage on the interweb at the moment: Dynamic typed languages; and languages that support concurrent programming. Both are important concepts that are driven by their own good reasons, but they exist in isolation in separate communities with very little overlap. Each is pursuing their own goals separately of the problems the other is trying to address (and making great progress with).
Dynamic Languages
Ruby, Python and their dynamic siblings are getting a lot of attention at the moment. There are good reasons for this which have been well discussed in the blogosphere, and I’m not going to churn out more flame bait by dredging them up again.
For all that dynamic languages have going for them, there is one big elephant in the room that no one wants to talk about much: They are dog slow, and they pay lip service to dealing with the changing CPU landscape. Slow has been fine for the past couple of decades. So you have a slow language. No problem. In a few years CPU clock rates will have doubled and it won’t be slow any more.
Problem these days is that clock speeds have been standing still for some time. The real action is in cramming more cores onto each CPU, and cramming more CPUs in your computer. If your Ruby app runs slow now - you’re in trouble. That is about as fast as it’s going to get. Maybe the next generation CPUs might creep up to 4ghz, but that’s about it. There are physical limits to this stuff, and we’re right on them. There is only so far circuits can be shrunk and clock speeds increased before electrons stop flowing round them.
This isn’t such a problem for Rails and other web apps. The standard response is that you throw more hardware, and separate OS processes at it, and this does work well for web apps that are dealing with isolated requests to a shared database. In this case, better faster hardware will save you, and this is a good thing. It lets developers get on with writing code rather than tweaking every last micro-optimisation out of their code. Joel Spolsky touched on that the other day.
But there are other apps that don’t work as well with the shared nothing scaling approach. I can think of a whole class of applications at Shine Technologies where there is a need for high throughput batch processing with a lot of data flying back and forth between parallel processes. Currently these are written in Java, but I’d love to be able to use a dynamic language like Ruby for them. It just isn’t an option though due to the poor performance. They need to run as a single app spread across multicore and/or multicpu and/or distributed CPUs. Ruby doesn’t make that so easy.
Which brings us to languages tailored to do exactly that:
Concurrent Languages
Erlang and other functional languages that allow massive concurrency are the other hot ticket item on the blog rounds these days. Message passing is seen as one of the saviors to guide us past the clock speed stagnation into proper parallel programing that doesn’t suck.
And to be honest, it looks like the best approach out there at the moment. The Erlang way is to use immutable state, asynchronous message passing, and extremely light-weight processes to enable concurrent, scalable applications. The fact it also makes it easy to scale apps across a distributed grid is the icing on the cake.
But as pointed out by Cédric Beust, the language itself is a little clunky. I’ve been working my way through Programming Erlang by Joe Armstrong as well, and I find myself constantly impressed by the concepts, but annoyed by the language. Maybe its because its unfamiliar, but compared to something like Ruby it just feels like more effort than it should be.
Which is the dirty secret of the concurrent crowd. Erlang is elegant and powerful, but not as accessible, fun or productive as dynamic languages are.
The bastard child of Erlang and Ruby
Both these types of languages have huge strengths, and some weaknesses that are solved by the other camp. But they exist almost totally independently of each other. When discussing one, it’s almost as if you’re in a different universe to the other. The concepts don’t intermingle at all.
What I’d love is some twisted love child of Erlang and Ruby. Something that would be something like:
- Variable state allowed. Erlang’s immutable variables are great for safe, fault tolerant systems, but not so great for actually playing with and evolving code. Safety and fault tolerance isn’t a specific requirement for concurrent systems (although it is a requirement for the type of systems Erlang is trying to build, which is fair enough). Muck with state as much as you want… but only within a process, because…
- Each process has separate address space. Nothing happening in one process is visible to any other. The only way to implicitly communicate is via Erlang style asynchronous message passing of copies of data. Maybe allow explicit shared memory between processes perhaps with some annotation to declare variables as shared.
- Light weight processes - let the VM figure out how to spread them across OS threads/cores/CPUs. Spawning 100,000 processes like in Erlang should be trivial and normal.
- It doesn’t necessarily have to be functional, but then it doesn’t necessarily have to be OO either. The exact programming style isn’t as important as separating state in each process. Erlang is implemented with Functional programming, but the concepts work in any kind of language.
Ultimately I think that they will both drift together as part of their natural evolution. I’m just surprised it hasn’t started to happen yet. When it does happen, it will probably from the dynamic side going more concurrent rather than the other way round. Dynamic languages have a hole in performance that can only be fixed with concurrent programming techniques. Where as users of concurrent languages are happy with the current functional approach and probably have less of a need to change their entire programming style.
Combining these two languages approaches together could make for a killer super language with the best of both worlds: The productivity, pleasure, and agile development offered by dynamic languages; with the performance and scalability increasingly available from concurrent focused languages as multi-core, multi-cpu boxes and distributed processing become standard.