[concurrency-interest] Single writer multiple readers no barriers -- safe ?

Vitaly Davidovich vitalyd at gmail.com
Fri Nov 29 18:13:37 EST 2013


If the field is volatile but accessed through unsafe direct member access,
I'm not sure whether the access is treated as volatile or not in that
case.  However, I don't see the point in marking the field as volatile and
accessing through unsafe and expecting compiler barrier - this is what
AtomicReference.get() will achieve.

At the end of the day, you need to make sure the reference of the hashmap
is read from memory so you can detect changes; you can read that into a
local and then read the actual hashmap internals from the cached address.
So you need a volatile load here (and on x86 and 64 this translates into
just compiler barrier, as mentioned before, which is pretty cheap).

Sent from my phone
On Nov 29, 2013 6:00 PM, "Thomas Kountis" <tkountis at gmail.com> wrote:

> That last part is a bit unclear. If we are marking a field as volatile and
> use the direct get (through Unsafe) how and why would JIT hoist
> instructions ? Isn't that what volatile guards from as well ?
>
>
> On Fri, Nov 29, 2013 at 10:44 PM, Vitaly Davidovich <vitalyd at gmail.com>wrote:
>
>> On x86 the volatile read isn't going to cost much of anything over a
>> normal one - it's just a compiler barrier.  If it's read often it'll be in
>> L1 cache and be just a few clocks.
>>
>> Using a naked read leaves you open to the scenario Nitsan mentioned
>> earlier in this thread.
>>
>> Sent from my phone
>> On Nov 29, 2013 5:02 PM, "Aaron Grunthal" <
>> aaron.grunthal at infinite-source.de> wrote:
>>
>>> Isn't the problem with both AtomicReferenceFieldUpdater and
>>> AtomicReference that they don't have a lazyGet? The get is equivalent to a
>>> volatile read. Only Unsafe can give you normal get and ordered put, i.e.
>>> safe single-writer publishing.
>>>
>>>
>>> On 29.11.2013 22:04, Vitaly Davidovich wrote:
>>>
>>>> AtomicReferenceFieldUpdater has some safety/defensive checking overhead,
>>>> IIRC.  Although with writes every 5 mins only I don't think the write
>>>> side perf matters all that much.
>>>>
>>>> Sent from my phone
>>>>
>>>> On Nov 29, 2013 2:37 PM, "Chris Vest" <mr.chrisvest at gmail.com
>>>> <mailto:mr.chrisvest at gmail.com>> wrote:
>>>>
>>>>     Note that AtomicReferenceFieldUpdater also has lazySet, so you don't
>>>>     need to go to the Unsafe if you want to avoid the indirection of
>>>>     AtomicReference.
>>>>
>>>>     --
>>>>     Chris
>>>>
>>>>
>>>>     On 29 November 2013 10:06, Thomas Kountis <tkountis at gmail.com
>>>>     <mailto:tkountis at gmail.com>> wrote:
>>>>
>>>>         Ok that makes sense.
>>>>
>>>>         I measured the performance and no this is not close to being a
>>>>         bottleneck on the current setup, since there are other places
>>>>         which are much slower. So the initial question was more into the
>>>>         "lets experiment" side of things and learn. My thinking was that
>>>>         since we only have one writer and thats only on a specific
>>>>         interval (5 mins) there would be a waste of using the CHM to
>>>>         host the data. Taking a snapshot of the current state during a
>>>>         write, replace of things and reassign the map variable to the
>>>>         snapshot seemed more interesting.
>>>>
>>>>         Thanks again :)
>>>>
>>>>
>>>>
>>>>         On Fri, Nov 29, 2013 at 8:42 AM, Nitsan Wakart
>>>>         <nitsanw at yahoo.com <mailto:nitsanw at yahoo.com>> wrote:
>>>>
>>>>             What could go wrong is:
>>>>                 while(getMap().get(key)){
>>>>                    // wait for key
>>>>               }
>>>>             Can in theory (and sometimes in practice) spin forever. The
>>>>             value gets hoisted and never checked again. The JIT assumes
>>>>             there's no way for the read value to change, so won't check
>>>>             again. At that point the 'at some point' becomes 'never'.
>>>>             Reading through your original post again I would take a step
>>>>             back and evaluate the performance win vs. correctness. Are
>>>>             you 100% sure this is a bottleneck for your program? have
>>>>             you tried and measured using CHM and it makes a measurable
>>>>             difference to use your alternative?
>>>>             If the answer to the above is "yes we did, and yes it does"
>>>>             then it would be good to see some concrete code to
>>>>             demonstrate how you are using this map.
>>>>
>>>>
>>>>             On Friday, November 29, 2013 10:01 AM, Thomas Kountis
>>>>             <tkountis at gmail.com <mailto:tkountis at gmail.com>> wrote:
>>>>             Thanks for the responses guys.
>>>>             I do understand all the above, but what I don't understand
>>>>             is what could go wrong with the no barrier approach on x86 ?
>>>>             Wouldn't that write eventually get flushed to main memory,
>>>>             and the other processors must invalidate cache at some point
>>>>             also ? I know this is a lot of "at some point", therefore, I
>>>>             guess its very vague to be trusted, but is there anything
>>>>             else apart from timing that could go wrong and that write
>>>>             not become visible?
>>>>
>>>>             t.
>>>>
>>>>
>>>>             On Fri, Nov 29, 2013 at 6:51 AM, Nitsan Wakart
>>>>             <nitsanw at yahoo.com <mailto:nitsanw at yahoo.com>> wrote:
>>>>
>>>>                  From my experience, lazySet is indeed your best choice
>>>>                 (but only a valid choice for a single writer). You need
>>>>                 a volatile read to match the HB relationship otherwise
>>>>                 the compiler is free to optimize the value you read, so
>>>>                 someone using your map in a loop may end up stuck if you
>>>>                 don't do it.
>>>>
>>>>
>>>>
>>>>                 On Friday, November 29, 2013 5:35 AM, Vitaly Davidovich
>>>>                 <vitalyd at gmail.com <mailto:vitalyd at gmail.com>> wrote:
>>>>                 AtomicReference.lazySet is the way to go here - on x86
>>>>                 this is just normal mov instruction with compiler
>>>>                 barrier only (StoreStore).  If you don't want overhead
>>>>                 of AtomicReference wrapper (doesn't sound like that
>>>>                 would be an issue) you can get same effect with
>>>>                 Unsafe.putObjectOrdered.
>>>>                 I wouldn't worry about AtomicReference.get() performance
>>>>                 on x86 - this is a read from memory but if you read
>>>>                 frequently, you'll hit L1 cache anyway.
>>>>                 HTH
>>>>                 Sent from my phone
>>>>                 On Nov 28, 2013 5:34 PM, "Thomas Kountis"
>>>>                 <tkountis at gmail.com <mailto:tkountis at gmail.com>> wrote:
>>>>
>>>>                     Hi all,
>>>>
>>>>                     This is my first time posting on this list, been
>>>>                     follower for quite some time now and really enjoying
>>>>                     all the knowledge sharing :) .
>>>>
>>>>                     I was looking on optimizing a solution today at
>>>>                     work, and I came across the following.
>>>>                     We have a scenario where we keep a simple cache
>>>>                     (HashMap) and this is accessed by multiple
>>>>                     readers on an application server, millions of times
>>>>                     per day and highly contented. This cache is
>>>>                     immutable and only gets updated by a single writer
>>>>                     by replacing the reference that the variable points
>>>>                     to every 5 mins. This is currently done as a
>>>>                     volatile field. I was looking for a way to lose
>>>>                     completely the memory barriers and rely on that
>>>>                     field being eventually visible across all other
>>>>                     threads (no problem by reading stale data for a few
>>>>                     seconds).
>>>>
>>>>                     Would that be possible with the current JMM ? I
>>>>                     tried to test that scenario with some code, and it
>>>>                     seems to work most of the times, but some threads
>>>>                     read stale data for longer that I would expect (lots
>>>>                     of seconds). Is there any platform dependency on
>>>>                     such implementation ? Its going to run on x86
>>>>                     environments. Is there any assumption we can make as
>>>>                     of how long that 'eventually' part can be ? (could
>>>>                     it be more than 5 mins, when the next write
>>>>                     occurs?). My understanding is that, that write even
>>>>                     if re-ordered will have to happen. I came across an
>>>>                     article about using the AtomicReference doing a
>>>>                     lazySet (store-store) for the write, and then the
>>>>                     Unsafe to do a getObject (direct) instead of the
>>>>                     default get which is based on the volatile access.
>>>>                     Would that be a better solution?
>>>>
>>>>                     Any ideas, alternatives?
>>>>
>>>>                     PS. Sorry for the question-bombing :/
>>>>
>>>>                     Regards,
>>>>                     Thomas
>>>>
>>>>                     _______________________________________________
>>>>                     Concurrency-interest mailing list
>>>>                     Concurrency-interest at cs.oswego.edu
>>>>                     <mailto:Concurrency-interest at cs.oswego.edu>
>>>>                     http://cs.oswego.edu/mailman/
>>>> listinfo/concurrency-interest
>>>>
>>>>
>>>>                 _______________________________________________
>>>>                 Concurrency-interest mailing list
>>>>                 Concurrency-interest at cs.oswego.edu
>>>>                 <mailto:Concurrency-interest at cs.oswego.edu>
>>>>                 http://cs.oswego.edu/mailman/
>>>> listinfo/concurrency-interest
>>>>
>>>>         _______________________________________________
>>>>         Concurrency-interest mailing list
>>>>         Concurrency-interest at cs.oswego.edu
>>>>         <mailto:Concurrency-interest at cs.oswego.edu>
>>>>         http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>>>
>>>>
>>>>     _______________________________________________
>>>>     Concurrency-interest mailing list
>>>>     Concurrency-interest at cs.oswego.edu
>>>>     <mailto:Concurrency-interest at cs.oswego.edu>
>>>>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Concurrency-interest mailing list
>>>> Concurrency-interest at cs.oswego.edu
>>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>>
>> _______________________________________________
>> 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/20131129/2a97e244/attachment-0001.html>


More information about the Concurrency-interest mailing list