Reduce object creation in STM
Reduce the number of TransactionTemplate objects created.
Also look at the Akka Transaction and TransactionLifecycleListener that are created for every TransactionTemplate.
Peter Veentjer (30 April):
You can reuse the TransactionTemplate; you can even share it between
threads; so create one instance in the beginning, and reuse that
instance.
Peter Veentjer (29 April):
by default the transactiontemplate used in akka also has the
lifecyclelisteners enabled. So for every transaction you start, some
administration (that never is used) needs to be done. If this is
disabled, it should also improve concurrency. In Multiverse I only
provide the transactiontemplate for convenience and integration with
other languages. But for the Java integration I inline the transaction
logic in the methods and do some other cool stuff that reduces
pressure on the transaction. So the current Akka implementation is not
at the performance it could be.
Peter Veentjer (6 May):
The TransactionFactory is 'expensive' and should be reused if possible. And without the TransactionFactory a lot of the speculative stuff doesn't work because everytime the learning process has to start from scratch. The TransactionFactoryBuilder is the place to do all transaction related configuration (a lot more stuff is expected like pessimistic locking, profiling, contention management etc etc).
It is best to create a static/final TransactionFactory for each actor class.. Or if actors are used for a long time, you could give each instance his own TransactionFactory but limits the scope of learning to instance level and not to class level and also increased memory usage.
So in case of an actor, on a technical level, you could do something like:
But this would prevents unwanted object creation to the extreme (in the 0.6 release even the transaction will be reused). This means that a readonly transaction will not create a single object and an update transaction will create an object per ref that is updated (this is because of the field granularity akka is using instead of object granularity which is also possible with multiverse).
Using this approach doing 10M update-transactions/second on a single core are possible and an order of magnitude more readonly transactions/second.
Very high frequent object creation kills performance so preventing object creation is completely integrated in the design of Multiverse.
Peter Veentjer (14 May):
With the default configuration of the TransactionTemplate you always have working lifecycle methods on the TransactionTemplate. The 'problem' is that you will always have the overhead of object creation and registration. That is why this behavior can be deactivated (see the constructor for the transactiontemplate for more information).
What you also can do is directly access the Transaction lifecyclelistener functionality only when a lifecycle callback really is needed (so you only pay the price when it is used). If a user wants to have a deferred executing task (so after a commit completes) or a compensating task (executed when the transaction aborts), you register a Runnable when needed.
You can wrap this in some Scala magic, but essentially what you need to do is:
If you add this logic in Akka, you don't need to expose Multiverse specific functionality in Akka, but you do have the
performance advantage since no unwanted registrations are done.
One of my committers is working on refactoring the TransactionTemplate so you don't need to subclass, but have a more
closure like approach where a function can be passed that needs to be executed inside a transaction.
Also look at the Akka Transaction and TransactionLifecycleListener that are created for every TransactionTemplate.
Peter Veentjer (30 April):
You can reuse the TransactionTemplate; you can even share it between
threads; so create one instance in the beginning, and reuse that
instance.
Peter Veentjer (29 April):
by default the transactiontemplate used in akka also has the
lifecyclelisteners enabled. So for every transaction you start, some
administration (that never is used) needs to be done. If this is
disabled, it should also improve concurrency. In Multiverse I only
provide the transactiontemplate for convenience and integration with
other languages. But for the Java integration I inline the transaction
logic in the methods and do some other cool stuff that reduces
pressure on the transaction. So the current Akka implementation is not
at the performance it could be.
Peter Veentjer (6 May):
The TransactionFactory is 'expensive' and should be reused if possible. And without the TransactionFactory a lot of the speculative stuff doesn't work because everytime the learning process has to start from scratch. The TransactionFactoryBuilder is the place to do all transaction related configuration (a lot more stuff is expected like pessimistic locking, profiling, contention management etc etc).
It is best to create a static/final TransactionFactory for each actor class.. Or if actors are used for a long time, you could give each instance his own TransactionFactory but limits the scope of learning to instance level and not to class level and also increased memory usage.
* <h2>Threadsafe</h2> TransactionTemplate is thread-safe to use and can be reused. So in case of an actor, you could
* create one instance in the beginning, and reuse the instance.
So in case of an actor, on a technical level, you could do something like:
class MyActor extends Actor{
static final TransactionFactory txFactory = GlobalStmInstance().getGlobalStmInstance().
.getTransactionFactoryBuilder()
.setSpeculativeConfigurationEnabled(true)
.setExplicitRetryAllowed(false)
.setReadonly(false)
.setTrackReads(true)
.build();
final TransactionTemplate template = new TransactionTemplate(txFactory){
public Object execute(Transaction tx){
.... user code
return null;
}
}
void receive(){
template.execute();
}
}
But this would prevents unwanted object creation to the extreme (in the 0.6 release even the transaction will be reused). This means that a readonly transaction will not create a single object and an update transaction will create an object per ref that is updated (this is because of the field granularity akka is using instead of object granularity which is also possible with multiverse).
Using this approach doing 10M update-transactions/second on a single core are possible and an order of magnitude more readonly transactions/second.
Very high frequent object creation kills performance so preventing object creation is completely integrated in the design of Multiverse.
Peter Veentjer (14 May):
With the default configuration of the TransactionTemplate you always have working lifecycle methods on the TransactionTemplate. The 'problem' is that you will always have the overhead of object creation and registration. That is why this behavior can be deactivated (see the constructor for the transactiontemplate for more information).
What you also can do is directly access the Transaction lifecyclelistener functionality only when a lifecycle callback really is needed (so you only pay the price when it is used). If a user wants to have a deferred executing task (so after a commit completes) or a compensating task (executed when the transaction aborts), you register a Runnable when needed.
You can wrap this in some Scala magic, but essentially what you need to do is:
static void registerDeferredTask(final Runnable task){
Transaction tx = getRequiredThreadLocalTransaction();
tx.registerLifecycleListener(new TransactionLifecycleListener() {
@Override
public void notify(Transaction tx, TransactionLifecycleEvent event) {
if (event == TransactionLifecycleEvent.postCommit) {
task.run();
}
}
});
}
If you add this logic in Akka, you don't need to expose Multiverse specific functionality in Akka, but you do have the
performance advantage since no unwanted registrations are done.
One of my committers is working on refactoring the TransactionTemplate so you don't need to subclass, but have a more
closure like approach where a function can be passed that needs to be executed inside a transaction.
Leave a comment
on 2010-06-02 19:29 *
By Peter Vlugter
Assigned to set to pvlugter
Status changed from New to Accepted