[concurrency-interest] Volatile/final and the JIT

Pierre Fourès pierre.foures at gmail.com
Thu May 7 11:59:53 EDT 2009


Just to note that the second example was indeed flawed.

The wait() method have to be invoked on the lock object for methods getFoo()
and method setStatistics(). I also omitted in method releaseFoo() to call
lock.notify() just after setting accessible to true in order to wake up an
eventually "setStatistics" pending threads.


Regards,

Pierre.

Le 7 mai 2009 16:05, Pierre Fourès <pierre.foures at gmail.com> a écrit :

> 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/6f6544bc/attachment.html>


More information about the Concurrency-interest mailing list