The first optimistic transaction library is now working. The results are rather satisfactory, but improvement is still needed. If you read on, some test results are described. This for-comprehension as a monad proved to be something that I had troubles to grasp, especially since all the different parts (for, flatMap, etc) are named as if they were only for the list comprehension. Anyway, it is now working.
I have also started implementing the library for the database access that will be optimised à la SLinks. Of course, it is quite uninteresting by itself without the changes to the compiler to support its optimisation. But there is a start for everything. Plenty of work remaining for this though.
Test results
Consider the following test environment. 100 threads all execute one transaction that will swap the value of two variables using one support variable (s:=x;x:=y;y:=s). The three used variables for every thread are randomly selected from a pool of 300 variables. That means that the different transactions share some data, but not too much. There are typically 70 transactions that share at least one variable with another transaction. During the execution of the swap function, the threads will each sleep for a randomly chosen time between 0 and 300 ms. This is of course only somewhat realistic (it might correspond to waiting for input or example) but I believe it is also a rather good indication of how well it might work in a multi-processor environment.
In this setting, the policy that locks down the whole system when doing a transaction takes a time around 16'000 ms in average. This is what one would expect as 100 threads times 150 ms (the average time a swap waits) is 15'000 ms plus the locking overhead. On the other hand, the optimistic policy is much faster: around 1000 ms (15 times less). The number of aborts are quite high, but it doesn't seem to be such a problem when compared to the other policy. I did not measure directly the average number of aborts per thread, but I tried to estimate it differently: If the number of aborts allowed for a given transaction is limited to 50, 2-5 percents of transactions will fail (that is, they would have aborted more than 50 times). With a abort limit of 100, the failure of a transaction is too rare to be detected (significantly less than 1%).
Of course, in unfavourable cases, the optimistic algorithm becomes very bad. The good news however is that the optimistic algorithm remains at least as good as the pessimistic one ... until it starts to completely wreak havoc on the system: since the abort mechanism is recursive with no tail call, it starts using up huge amounts of memory and the threads fail because they run out of memory. I will have to improve this.