January 29, 2006

Fun with transactional programming environments

Or maybe it should be titled "Pondering transactional programming environments".

I've been thinking about this the past day or so. I'm not thinking so much the standard two-phase multi-connection RDMBS style transaction, but rather the sort of transactional things folks are talking about these days with programming languages. Y'know, where you basically snapshot everything and if something happens you just put your old values back. Folks talk about this with the whole 'black box programming' model as well, where you take and record snapshots of state so you can put things back in case something goes Horribly Wrong.

Now, I don't think this is something I'm going to design into the engine (though it could be really cool for doing massive simulations -- restore a snapshot, tweak some values, and see how things progress) but that doesn't mean I haven't been thinking about it.

The big reason for thinking about it is that, so far as I can tell, the things that you need to make transactional stuff work fast and well are some of the same things you need to do heavy multithreading well. If you have the sort of isolated system I was talking about earlier, the sort that makes pausing and nuking threads easy, then you've got what you need to do transactions, and you've got them easy. (Especially if you go as far as Erlang does, with single-write variables)

So, you want to snapshot. What do you do? Well, if you've got immutable variables (or a reasonable facsimile) then taking a snapshot's just a matter of copying the variable heads (as well as any spot that may refer to them, such as the stack or any registers if you use them) off to a spot that the garbage collector, if you have one, can find them so garbage doesn't get collected. The total time taken is proportional to the number of variables you've got, rather than the amount of data you have. Noting that a snapshot's been taken is useful for creating true transactions, since there are things that should be disallowed while a valid transaction is in progress. (For example, any external call that can't be guaranteed to be repeatable would be disallowed -- possibly IO, interprocess or inter-thread communication, calls to external libraries under many circumstances, and suchlike things)

Yeah, it's definitely limiting, but... it's also very useful. Straight non-transaction snapshotting gives you the potential to investigate how a program is running after the fact without having to grovel through a core dump (or even having to take a core dump) if you can also write the contents of memory to disk along with the snapshot (essentially freezing and thawing the entire variable store) providing the black box effect that many folks want, and if you've got reasonably safe memory access you don't even have to save them to disk -- you can just take repeated snapshots and have them accumulate up in memory for later investigation if the program does die.

It's definitely nifty, that's for sure. 'Specially if you snapshot groups of threads -- in that case you can allow inter-thread communication, since you can then roll back state without any of the threads knowing, which is cool too. And definitely handy for sharing simulations, but that's just what's caught my eye at the moment.

Posted by Dan at January 29, 2006 02:29 PM | TrackBack (0)

Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice Herlihy, "Composable Memory Transactions".
ACM Conference on Principles and Practice of Parallel Programming 2005 (PPoPP'05).

There are a couple of other papers at Simon Peyton Jones' page I trust you'll find interesting...

Posted by: Peter Lund at February 3, 2006 04:40 PM