|Ariel Weisberg||Feb 13, 2013 12:41 pm|
|Vitaly Davidovich||Feb 13, 2013 12:51 pm|
|Ariel Weisberg||Feb 13, 2013 1:45 pm|
|Vitaly Davidovich||Feb 13, 2013 2:15 pm|
|Aaron Grunthal||Feb 13, 2013 7:37 pm|
|Chris Dennis||Feb 14, 2013 8:15 am|
|Ariel Weisberg||Feb 14, 2013 8:56 am|
|Vitaly Davidovich||Feb 14, 2013 9:31 am|
|Nathan Reynolds||Feb 14, 2013 9:41 am|
|Subject:||Re: [concurrency-interest] Using Atomic*FieldUpdater to remove indirection|
|From:||Nathan Reynolds (nath...@oracle.com)|
|Date:||Feb 14, 2013 9:41:18 am|
Will storing the volatile field onto a stack variable give me a
snapshot of the value?
Yes. The typical strategy is to copy the field into a stack variable, check the state using the stack variable, calculate the updates based off of the stack variable and apply the update to the volatile field using 1 atomic instruction.
Another question I have is about the padding suggestion. I looked at
how it is done in Exchanger with the 15 long fields. What guarantees are there for field ordering and alignment of the allocated object WRT to cache lines? It seems like you might need to pad both before and after the field that is contended.
There are no guarantees for field ordering. The JVM will rearrange the fields for its needs. For example, it will sort the primitive fields by width and put the wider ones first so that no padding is necessary between fields. It will then put all of the references last to help GC performance. So, if you are looking to avoid false sharing among fields in the class you are out of luck until @Contended is available. I think it is/will be available in HotSpot 8.
15 * sizeof(long) = 120 bytes. Add 8 bytes for the object header (i.e. 32-bit JVMs) and the total is 128 bytes. This is exactly 2 cache lines. If multiple Exchangers are next to each, then the fields can never be on the same cache line no matter where in the cache line the initial byte of the object is placed. If the protected field ends up at the end of the object, then I don't see how this would protect it from false sharing with a different type of object which has a heavily written field at the beginning. I figured to achieve ultimate false sharing protection, then I have to put the protected field in the middle of an array. The array must have 64 bytes on both sides of the protected field. In other words, the array is 128 bytes long + the size of the protected field. For example, an int would protect an int stored at position 16. This doesn't account for the 12 byte object header (32-bit JVM). So, the actual array length could be 3 elements shorter with the protected int stored at position 13.
Is there a difference between storing a reference to a properly
padded object for contended fields vs adding the padding directly to the object containing the contended field?
You have to put the padding around the contended field in order to protect it from false sharing.
What about array fields (primitives, and objects), are they ever
stored inside the object or are they always separate allocations?
Arrays are always individual objects and can be placed anywhere in the heap.
Nathan Reynolds <http://psr.us.oracle.com/wiki/index.php/User:Nathan_Reynolds> | Architect | 602.333.9091 Oracle PSR Engineering <http://psr.us.oracle.com/> | Server Technology On 2/14/2013 9:56 AM, Ariel Weisberg wrote:
I only need this to work on x86_64 so I should be fine with volatile
reads of references. The only path that has to be fast is reading the
field, updating can be slow (and is).
Will storing the volatile field onto a stack variable
give me a snapshot of the value? Another question I have is about the padding suggestion. I looked at how it is done in Exchanger with the 15 long fields. What guarantees are there for field ordering and alignment of the allocated object WRT to cache lines? It seems like you might need to pad both before and after the field that is contended. Is there a difference between storing a reference to a properly padded object for contended fields vs adding the padding directly to the object containing the contended field? What about array fields (primitives, and objects), are they ever stored inside the object or are they always separate allocations? Thanks, Ariel On Thu, Feb 14, 2013, at 11:15 AM, Chris Dennis wrote:
My understanding is that doing that is not technically (per the JDK spec) safe. The updaters don't guarantee atomicity of their changes with respect to other mutations. On Hotspot I think you can only see this behavior for AtomicLongFieldUpdater when the underlying hardware lacks an 8 byte compare-and-swap (which obviously makes sense).
On Feb 13, 2013, at 10:37 PM, Aaron Grunthal wrote:
Btw, Atomic*Updaters are not entirely equivalent to raw
volatile/CAS accesses due to a bunch of security checking they do. Especially when security domains are used or the Updater's target class has subclasses then it has to do some checks that the JVM cannot optimize away. So if every ounce of performance counts you probably should do volatile reads and writes to the field handled by the updater directly and only use it for CAS. And as last resort there's also Unsafe, but there usually are bigger fish to fry before you get to that point.
On 13.02.2013 21:41, Ariel Weisberg wrote:
Does it make sense to use Atomic*FieldUpdater to remove the indirection overhead of an AtomicLong and AtomicReference? Similarly, does it make sense to use Atomic* to create indirection in order to avoid false sharing?