[concurrency-interest] Volatile/final and the JIT

Pierre Fourès pierre.foures at gmail.com
Thu May 7 10:05:34 EDT 2009


Hello Peter,

An other approach, not based on the ability of the JIT optimizing your code,
could merge benefits of the two approach : keeping the ability to update the
statistics variable while not adding overhead of a volatile variable, at the
expense of increased code complexity.


The way I understand your problem make me believe the foo() method
invocation ratio should be quite high over the amount of updates between
having or not statistics for your foo object. I also presume the clients of
your foo objects accomplish some kind of large amount of treatments
split over some kind of "work units".


If this is the case, you may want to encapsulate your foo instance behind
some kind of monitor. Access to the foo instance would go through the
monitor and a synchronized bloc would ensure the memory visibility over the
"statistics" field. The same technique would be used to set or unset the
FooStatistics object on the foo instance.


You could use something like this :


FooMonitor {

    private final Foo foo;


    FooMonitor(Foo foo) {

        this.foo = foo;

    }


    public synchronized Foo getFoo() { return foo;}


    public synchronized void setStatistics(FooStatistics stats} {

        foo.setStatistics(stats);

    }

}


While this approach is more slow than accessing a single volatile field this
code is invoked much more rarely and could/should outperform the use of the
volatile field. However, note that you can't predict if the current working
unit may eventually see or not the update in the middle of its execution.


For statistics purposes this might sound ok but depending on your needs and
requirements you could use a mutual exclusion policy over the foo instance
in order to grant when the statistic object would be visible by the clients
of the foo instance. This last point make the solution even more complex and
requires strong coding discipline and extensive testing.


The (probably wrong) sketch currently in my mind would look like this (with
no fairness consideration in mind) :


FooMonitor {

    private final Foo foo;


    private boolean accessible = true;

    private Object lock = new Object();


    FooMonitor(Foo foo) {

        this.foo = foo;

    }


    public Foo getFoo() {

        synchronized(lock) {

            while(!accessible) wait();

            accessible = false;

            return foo;

        }

    }


    public void releaseFoo() {

        synchronized(lock) {

            accessible = true;

        }

    }


    public void setStatistics(FooStatistics stats} {

        synchronized(lock) {

            while(!accessible) wait();

            foo.setStatistics(stats);

        }

    }

}


Of course both solutions should only be considered under extreme seek for
performance (but if for you every read/write to CAS/volatile variables
counts, this seems to be the case.) and I even wouldn't consider using the
last solution with only the argument of performance in mind (I would rather
upgrade the server or add a node to the cluster).


Regards,

Pierre.

2009/5/5 Peter Veentjer <alarmnummer at gmail.com>

> I have a question about the JIT and optimisations.
>
> Is the JIT able to remove conditions based on volatile fields?
>
> e.g.
>
> class FooStatistics{.....}
>
> class Foo{
>
>   private final FooStatistics statisics;
>
>   public Foo(FooStatistics statistics){
>       this.statistics = statistics
>   }
>
>   void foo(){
>      ... some logic
>
>      if(statistics!=null)
>           statistics.incSomeCasCounter();
>   }
>
> }
>
> If I create a Foo with a null as statistics, the statistics part is
> completely removed and my foo method is transformed to:
>
> void foo(){
>    ..... some logic
> }
>
> The problem is that you can't activate/deactivate statistics on an
> existing object. So you could create something like this:
>
> class Foo{
>
>   private volatile FooStatistics statisics;
>
>   public Foo(FooStatistics statistics){
>       this.statistics = statistics
>   }
>
>   public void setStatistics(FooStatistics statistics){
>      this.statistics = statistics;
>   }
>
>   void foo(){
>      ... some logic
>
>      if(statistics!=null)
>           statistics.incSomeCasCounter();
>   }
>
> }
>
> In this case I presume the JIT will have a very hard time removing the
> statistics logic and as an additional cost, the system needs to access
> an 'expensive' volatile variable.
>
> I'm working on an STM implementation, and every read/write to
> CAS/volatile variables counts..
>
> So.. can anyone tell me if the final approach is the only way to go?
> Or is the JIT able to do some magic like speculative removal of code..
> and re-adding it if it is needed?
>
> Peter
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090507/96dcda6f/attachment-0001.html>


More information about the Concurrency-interest mailing list