New stuff for Multiverse 0.7 STM

The last few months I have been working very hard on the 0.7 release of Multiverse. And it is going to gain a lot of new goodes:

  1. new engine: a new STM engine has been added that is better scalable and better performing than the current TL2 (MVCC) based AlphaSTM. There are 2 reasons for this: much more object pooling (I pool almost everything) and removal of the central commit counter that needs to be increased when an updating transaction commits. The new BetaSTM engine is based on the SkySTM although I have taken a different approach for easing on concurrent arrives/departs.

    It will also be the the basis for making a distributed stm possible since the central commit counter will not scale (and a conflict counter used in the new BetaSTM can be striped). The new engine also relies heavily on templating (using Velocity) to generate multple transaction implementations and methods optimized for certain behavior or types of references. This is done when the Multiverse jars are build and there will no runtime dependency on Velocity.

  2. propagation levels: just like with databases you can specify requires, requiresnew, supported etc so you have fine grained control on the nesting of transactions.
  3. pessimistic behavior: which makes the stm more like traditional lock based concurrency control without the standard problems (race problems, deadlocks) and where operations still benefit from the standard stm advantages (composability of transactions, failure atomicity, isolation). It can be configured on transaction level
    for all reads or for all writes. But it also can be done on transactional object (reference) level for fine grained control
  4. rollback on: so you can specify when a transaction should abort/commit when an exception happens. Atm a transaction will always be aborted and with this behavior your have more control.
  5. commuting behavior: to make higher concurrency possible by allowing certain interleavings of transactions. This was already available in the 0.5 release, but user supplied functions were not possible and in the 0.7 release will be.
  6. Clojure semantics to make Multiverse usable in any Java project without relying on Clojure:
    1. commute. One of the differences of the Clojure approach is that the commuting function will not be reevaluated at the end if somehow a dependency was created on the value. This means that the resulting state always will be correct.
    2. add-watch: to make it possible to listen to change on a single ref. This lifts on the same
      mechanism as the retry, but the big difference is that you can listen on a single ref, instead of all reads.
    3. ensure: the prevent writeskew problems. One of the differences compared to the clojure approach is that you also can block on ref that has been ‘ensured’ not to change. This behavior lifts on the pessimistic support. Writeskew prevention in Multiverse already is available on the transaction level btw.
    4. alter: to apply a function on a reference. Not very interesting itself. The big difference with Clojure is that there will not be any boxing.

The properties also are going to be exposed in Akka; so you can expect a lot of new functionality there. The focus for the 0.7 release will mainly be to provide a half fabricate that can be used in other Java projects without relying on instrumentation. This will probably not be completely up to date.

I’m also working on an experimental storage engine to make durable transactions possible. But I don’t think it will be complete for the 0.7 release.

About these ads

4 Responses to New stuff for Multiverse 0.7 STM

  1. Andrew Phillips says:

    Any ideas yet on what the relase date might be..?

  2. pveentjer says:

    I don’t know. There still is a couple of months of work. Most of the new and AlphaSTM functionality already is added, but needs improved testing and I also need to make it compatible with the existing Multiverse API so that it can be used as drop in replacement.

  3. Jani Laakso says:

    Multiverse is very interesting project. Care to share what kind of persistency solution you are working on?

    Have you considered object or system prevalence as an storage concept? Implementation is extremely simple, works well on object oriented world and the performance is something that RDBM’s just can’t achieve. Personally I like it most because it’s lightning fast and I can do all in Java using object oriented methods. With RDBM’s it’s a pain to cope with object-relational impedance mismatch and performance requires lots of hardware and expensive coding. Now there’s downsides too (memory requirements), but this path could provide one interesting persistency solution which would be easy to implement.

    Object prevalence (/transparent persistency) paired with Multiverse would be a dream come true, at least on some commercial projects our company is producing. I’ll be looking closely this project on the future.

    See http://en.wikipedia.org/wiki/System_Prevalence or Prevayler project. Note that core Java implementation is very simple to implement.

  4. Oliver Plow says:

    Hello,

    I have a question concerning the Multiverse sample on http://multiverse.codehaus.org/60second.html. I have composed this little Multiverse test program using multiverse-
    alpha-0.7-20100822.092846-1.jar. When I run AccountTest.main I would expect that 100 and 0 to be printed onto the console. Because of the
    exception thrown in Account.setBalance no changes are commit, neither for Thread th1 not Thread th2.

    However, the program prints 10 and 90 onto the console:

    20.02.2012 17:12:13 org.multiverse.api.GlobalStmInstance
    INFO: Initializing GlobalStmInstance using factoryMethod
    ‘org.multiverse.stms.alpha.AlphaStm.createFast’.
    20.02.2012 17:12:13 org.multiverse.stms.alpha.AlphaStm
    INFO: Created a new AlphaStm instance
    20.02.2012 17:12:13 org.multiverse.api.GlobalStmInstance
    INFO: Successfully initialized GlobalStmInstance using factoryMethod
    ‘org.multiverse.stms.alpha.AlphaStm.createFast’.
    Exception in thread “Thread-2″ java.lang.IllegalStateException:
    negative balance not allowed
    at scratch.Account.setBalance(Account.java:31)
    at scratch.Account.transfer(Account.java:40)
    at scratch.AccountTest.run(AccountTest.java:57)
    at java.lang.Thread.run(Thread.java:619)
    10
    90

    I don’t understand this. Am I getting something wrong or is there a
    coding error in my test code?

    Thanks for any hints.
    Cheers, Oliver

    ———————————————- begin Account.java
    ———————————————-
    package scratch;

    import java.util.Date;
    import java.util.concurrent.CountDownLatch;

    import org.multiverse.annotations.TransactionalMethod;
    import org.multiverse.annotations.TransactionalObject;
    import org.multiverse.transactional.refs.BasicRef;
    import org.multiverse.transactional.refs.IntRef;
    import org.multiverse.transactional.refs.Ref;

    @TransactionalObject
    public class Account {

    private Ref lastUpdate = new BasicRef(new Date());
    private IntRef balance = new IntRef(100);

    public Account(int balance){
    setBalance(balance);
    }

    public int getBalance(){
    return balance.get();
    }

    public void setBalance(int newBalance){
    lastUpdate.set(new Date());

    if(newBalance < 0){
    throw new IllegalStateException("negative balance not
    allowed");
    }
    balance.set(newBalance);
    }

    @TransactionalMethod
    public static void transfer(Account from, Account to, int amount,
    CountDownLatch latch) throws InterruptedException{
    int newBalance = from.getBalance()-amount;
    latch.await();
    from.setBalance(newBalance);
    to.setBalance(to.getBalance()+amount);
    }

    }

    ———————————————- end Account.java
    ———————————————-

    ———————————————- begin AccountTest.java
    ———————————————-

    package scratch;

    import java.util.concurrent.CountDownLatch;

    public class AccountTest implements Runnable {

    public Account from;
    public Account to;
    public int amount = 0;
    public CountDownLatch latch;

    public AccountTest() {
    super();
    }

    public AccountTest(Account from, Account to, int amount,
    CountDownLatch latch) {
    super();
    this.from = from;
    this.to = to;
    this.amount = amount;
    this.latch = latch;
    }

    public static void main(String args[])
    {
    try {
    Account from = new Account(100);
    Account to = new Account(0);
    CountDownLatch latch = new CountDownLatch(1);

    AccountTest test1 = new AccountTest(from, to, 90, latch);
    AccountTest test2 = new AccountTest(from, to, 110, latch);

    Thread th1 = new Thread(test1);
    Thread th2 = new Thread(test2);

    th1.start();
    th2.start();

    Thread.sleep(2000);

    latch.countDown();

    Thread.sleep(2000);

    System.out.println(from.getBalance());
    System.out.println(to.getBalance());
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }

    @Override
    public void run() {
    try {
    Account.transfer(this.from, this.to, amount, latch);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

    }

    ———————————————- end AccountTest.java
    ———————————————-

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: