Tuesday, December 04, 2007

State Stinks! Part II

State Stinks! alright. My previous rant should have sufficed but I haven't succeeded in getting problems with state off of my chest! What could have I forgotten that would require its own posting! I had forgotten to mention the most worrisome of all forms of state - a form of state that I will refer to as uber-state.

To recap my previous post, I tried to illustrate how much of a software developer's life is spent managing and maintaining state. I also pointed out that many of our problems are self-inflicted, we trade a few gray hairs to optimize performance - some times just out of habit. All of these problems are intensified in multi-threaded applications. In short, state maintenance limits what we can accomplish with multi-threaded applications.

Uber-State - What we need is a supreme form of state that lives above normal application-maintained state. Some ancient guy said "give me a long enough pole and a fulcrum out in space and I can move the world" (or something to that effect). What we need is a fulcrum out in space. Easy enough, our application's supreme entity is the operating system. What we need is state that is managed by the OS that we can use as leverage points to assert control of our application. Right? Well this is what we current use to wrangle multi-threaded applications. Operating systems provide objects that we can use to synchronize thread operations and they work as designed.

But even Uber-State Stinks! - I am not trying to be difficult here! Let me explain. Operating System thread synchronization objects are very simple and are typically referred to as "primitives". To really harness the power of multi-threaded applications in a multi-core processor world, I need complete control of the operational state of my application. I don't just need to synchronize threads, I need to orchestrate my application. Uber-State you say (actually I said it) - horsefeathers!

I had mentioned in my previous post that naive OO designs typically ignore an application's operational state, treating state like a second-class citizen.

Using OS thread synchronization primitives has the same effect. Our applications rely on big-brother to adjucate and control access to state - leaving our application's state machine in disarray.

State doesn't have to stink - State needs to be first class citizen in our applications and work the way we would expect!

So where am I going with this? To begin with, let it be known that I do not only mean to prescribe to others with my postings, but I also wish to elicit suggestions. A former colleague, Jeff Moser, suggested that I look into Erlang. I have listened to his suggestion and my findings are fuel for my next posting to be entitled "Erlang Eureka!".

1 comment:

Jeff Moser said...

The problem with OS synchronization primitives like semaphores and mutexes (or abstractions like .NET's Monitor class from which we get the C# lock primitive) is that they just don't scale well to high degrees of parallelism.

It's like you need, to put it in your own words, an uber-dictator controlling everything. That is, making sure only one person gets inside the gate (e.g. critical section/lock) at a time. This isn't the way we think in the real world. We have a natural sense of dealing with concurrency. Erlang has support for this baked in.

Another manifestation is to change your programming style just slightly to totally eliminate the need for OS primitives for locks. This idea is what's behind the immutable data structures and "lock-free" algorithm push right now. Microsoft is especially interested in them and is hiring quite a few people to work on .NET 4.0 which will have Joe's ParallelFX ideas built in. As an example, check out Eric's Immutable Stack. It's a beautifully simple idea that shows how efficient immutable things can be. A bit more complicated example is Julian Bucknall's lock-free linked list.

Another variant on these ideas is the idea of software transactional memory (STM). That is, memory that your code uses that can handle transactions. This is what you need to handle the world where you're more optimistic about concurrency and your algorithms always try to do things rather than wait for a lock. If they mess up, they just clear the slate and try again. Databases have had this for years. I don't think it'll make it into .NET 4.0, but probably hit in .NET 4.5 or 5.0. Keep an eye on the Microsoft job postings like this one to get a feel for how serious Microsoft is about getting rid of the idea of state as we know it. It's too stinky for the upcoming world of multicores and heterogeneous cores.