DirectByteBuffers and reachabilityFence

classic Classic list List threaded Threaded
148 messages Options
12345678
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
On 12/09/2015 05:53 PM, Gil Tene wrote:

> My take on this would be to change the JLS and JVM spec to state
> that 'this' remains reachable until after the last instruction of
> every instance method. Period. This would basically equate to
> placing an implicit reachability fence at all exist points of every
> instance method (I.e. The equivalent of a try...finally). The "nice״
> thing about such an implicit reachability fence is that it does not
> really defeat any optimizations, as it only serves to extend the
> lifetime of an oop (so potentially pressing slightly harder on the
> register allocator). IMO this would auto-magically fix lots of
> current rarely occurring bugs (like those on DBB, but also in user
> code), and prevent many future ones.

Mmmm.  That's what I said!  One other advantage to doing this
automagically is that you won't get all these Java devs arguing about
whether the reachabilityFence really was needed.

Andrew.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Alexandre De Champeaux
In reply to this post by Vitaly Davidovich
 
Ok, I buy that.  I can't help but wonder how DBB authors decided it's ok to release it to the public like this though.  Granted, I can't think of a (realistic) scenario where allocating a DBB that's immediately garbage is normal.

I don't see why only DBB that are immediately garbage would be affected.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Andrew Haley
I don't think it'd be measurable.  A global volatile write is pretty
cheap.  And I'm sure there are several such writes when queuing a
finalizer.

The global volatile gets hit once, when the object is finalized.  Not
at every access, which is what you'd have to do with a compiler
barrier. 

Perhaps I misunderstood your global volatile suggestion -- when is it written to exactly? What's the usage?

Compiler barriers have a huge effect because they break many
loop optimizations.  That's a no-hoper.

That's true.  That's another reason to intrinsify reachabilityFence() since, in its current form, it will be exactly like a compiler barrier.
 

On Wed, Dec 9, 2015 at 1:40 PM, Andrew Haley <[hidden email]> wrote:
On 12/09/2015 02:36 PM, Vitaly Davidovich wrote:
> sent from my phone
> On Dec 9, 2015 5:33 AM, "Andrew Haley" <[hidden email]> wrote:
>>
>> On 08/12/15 19:17, Vitaly Davidovich wrote:
>>>> [me:]

>>> So now I'm going to write to dummy fields? And what are you going to
>>> do with it in a finalizer?
>>
>> Update a global volatile.
>
> And take perf hit? No thanks

I don't think it'd be measurable.  A global volatile write is pretty
cheap.  And I'm sure there are several such writes when queuing a
finalizer.

>>> And of course, a Sufficiently Smart Compiler could detect
>>> (theoretically, of course :)) that this is all just dummy ops and
>>> remove them.
>>
>> No, it can't.  Because the JLS says so.  IMVHO it'd be much better to
>> stop trying to guess what a compiler might do and simply write in the
>> language instead.
>
> JLS prescribes observable behavior not exact steps.

Well, yes.  Indeed it does.

>>> In my opinion, the current lack of optimization (accidental or not)
>>> should be somehow encoded/made intentional.
>>
>> I have in the past argued that methods of classes with finalizers
>> should automagically extend the lifetime of the "this" object.
>> However, I was on the losing side, and reachabilityFence() is the
>> compromise result.  That's okay, really: it solves the practical
>> problem.
>>
>>> Perhaps treat Unsafe::anything() as a full compiler optimization
>>> fence, if it's not already.
>>
>> That one really is a no-hoper.  The idea of NIO ByteBuffers is "as
>> fast as C" and full fences would be a pretty major regression.
>
> Maybe you missed the "compiler" part.

Not at all.

> I'm suggesting a compiler-only fence.  And I like how you suggested
> updating a global volatile above but here a full fence (which isn't
> what I proposed) is a no-hoper.

The global volatile gets hit once, when the object is finalized.  Not
at every access, which is what you'd have to do with a compiler
barrier.  Compiler barriers have a huge effect because they break many
loop optimizations.  That's a no-hoper.

Andrew.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Alexandre De Champeaux
Let me rephrase -- most DBB usage is such that the DBB is live until all things using it are.

On Wed, Dec 9, 2015 at 1:48 PM, Alexandre De Champeaux <[hidden email]> wrote:
 
Ok, I buy that.  I can't help but wonder how DBB authors decided it's ok to release it to the public like this though.  Granted, I can't think of a (realistic) scenario where allocating a DBB that's immediately garbage is normal.

I don't see why only DBB that are immediately garbage would be affected.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
In reply to this post by Vitaly Davidovich
On 12/09/2015 06:52 PM, Vitaly Davidovich wrote:

>>
>> I don't think it'd be measurable.  A global volatile write is pretty
>> cheap.  And I'm sure there are several such writes when queuing a
>> finalizer.
>
>
>> The global volatile gets hit once, when the object is finalized.  Not
>> at every access, which is what you'd have to do with a compiler
>> barrier.
>
> Perhaps I misunderstood your global volatile suggestion -- when is it
> written to exactly? What's the usage?

In the finalizer.  The idea is that you keep a counter in the
object and then write it to a global when finalized.  I don't
think this can be done much more cheaply without changes to
the compiler, and it's certainly much cheaper than the current
implementation of reachabilityFence.

Andrew.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Gil Tene-2
In reply to this post by Alexandre De Champeaux

On Dec 9, 2015, at 10:48 AM, Alexandre De Champeaux <[hidden email]> wrote:

 
Ok, I buy that.  I can't help but wonder how DBB authors decided it's ok to release it to the public like this though.  Granted, I can't think of a (realistic) scenario where allocating a DBB that's immediately garbage is normal.

I don't see why only DBB that are immediately garbage would be affected.

Like Alexandre, the current bug-tripping scenario that keeps me up at night is not the strange allocate-and-immediate-garbage case, but the last-use case. As in the behavior of the last get or put into a buffer that has been around for a while. These last accesses currently race with the cleaner's execution, and can result in reading from or writing to free'd (and potentially already allocated elsewhere) memory.

I believe that the reason this is "rare" dynamically is that most DBB uses we run into make fairly static use of DBBs, either managing their internal contents themselves (in various off heap memory patterns) or using them as a long lasting communications buffer (in various io and JNI setups). These use cases usually contain the race's exposure to the rare end-of-life events of the DBB, which often coincide with the program's end-of-life. Basically, the likelihood of completing a GC and running the cleaner within the race window, coupled with the actual access to the freed memory causing some actual problem (a SEGV or bad data being read that actually affects the program's behavior) in these situations is not 0, but is "fairly low".

But then there are the applications that make heavy dynamic use of DBBs, allocating and releasing them constantly. I'm dealing with one such app that is doing this with multiple TB of DBB managed memory, in tons of little chunks that come and go all the time, and some significant GC pressure as well, and it's those sort of apps that IMO are currently exposed to the inherent last-use race in DBB. 

— Gil.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (859 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Gil Tene-2
In reply to this post by Andrew Haley

> On Dec 9, 2015, at 10:26 AM, Andrew Haley <[hidden email]> wrote:
>
> On 12/09/2015 05:23 PM, Gil Tene wrote:
>>
>>> On Dec 9, 2015, at 9:18 AM, Andrew Haley <[hidden email]> wrote:
>>>
>>> On 12/09/2015 04:16 PM, Vitaly Davidovich wrote:
>>>>>
>>>>> an implicit implication that 'this' must remain reachable until after the
>>>>> last instruction in each of its instance methods
>>>>
>>>> Why wouldn't this work, at least as a compromise?
>>>
>>> It would, but it would hurt performance because of increased register
>>> pressure.
>>
>> Actually, it would only add a stack slot. And a spill into it if needed.
>
> Hesitant as I am to argue with you, I'm not so sure.  There'd
> definitely have to be a USE in order to keep the oop alive, and C2
> would surely try not to spill the oop.  The USE would be at the end of
> every method.  Unless there's some sort of "sink" node in the ideal
> graph which keeps an oop alive but does not refill from a stack slot,
> and I don't think there is.
Well, this all depends on how it's actually implemented.

Implementations can vary from an opaque non-inlineable method call that takes the 'this'
ref as an argument, to ones that just maintain a USE on the exit paths that doesn't get
optimized away (and as you note may mislead/drive the register allocator to want to keep the
thing in a register), to ones that somehow eliminate the actual use and the wish to hold
it in a register for that use, but prevent the recycling of the virtual register and/or associated
stack slot.

What is minimally required is that the oop remain around in the frame, and for it to be
described in the oopmaps. Which is why I see the minimal cost as that stack slot and the
potential spill into it.

> Andrew.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (859 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Andrew Haley
I don't see how this extends the lifetime of the object unless, at minimum, you increment the counter at each operation where you want to extend the lifetime.  And at this point, you may as well just stick reachabilityFence(this) inside the finalizer then.

On Wed, Dec 9, 2015 at 2:03 PM, Andrew Haley <[hidden email]> wrote:
On 12/09/2015 06:52 PM, Vitaly Davidovich wrote:
>>
>> I don't think it'd be measurable.  A global volatile write is pretty
>> cheap.  And I'm sure there are several such writes when queuing a
>> finalizer.
>
>
>> The global volatile gets hit once, when the object is finalized.  Not
>> at every access, which is what you'd have to do with a compiler
>> barrier.
>
> Perhaps I misunderstood your global volatile suggestion -- when is it
> written to exactly? What's the usage?

In the finalizer.  The idea is that you keep a counter in the
object and then write it to a global when finalized.  I don't
think this can be done much more cheaply without changes to
the compiler, and it's certainly much cheaper than the current
implementation of reachabilityFence.

Andrew.



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Andrew Haley
It may still be needed when you need to extend the lifetime of an object you hold but that would otherwise be early reclaimable.  But that's a much more minimal use case, which is why I said the advantage is that rF() would be used in much fewer places.

On Wed, Dec 9, 2015 at 1:40 PM, Andrew Haley <[hidden email]> wrote:
On 12/09/2015 05:53 PM, Gil Tene wrote:

> My take on this would be to change the JLS and JVM spec to state
> that 'this' remains reachable until after the last instruction of
> every instance method. Period. This would basically equate to
> placing an implicit reachability fence at all exist points of every
> instance method (I.e. The equivalent of a try...finally). The "nice״
> thing about such an implicit reachability fence is that it does not
> really defeat any optimizations, as it only serves to extend the
> lifetime of an oop (so potentially pressing slightly harder on the
> register allocator). IMO this would auto-magically fix lots of
> current rarely occurring bugs (like those on DBB, but also in user
> code), and prevent many future ones.

Mmmm.  That's what I said!  One other advantage to doing this
automagically is that you won't get all these Java devs arguing about
whether the reachabilityFence really was needed.

Andrew.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Gil Tene-2
In reply to this post by Andrew Haley

> On Dec 9, 2015, at 10:40 AM, Andrew Haley <[hidden email]> wrote:
>
> On 12/09/2015 05:53 PM, Gil Tene wrote:
>
>> My take on this would be to change the JLS and JVM spec to state
>> that 'this' remains reachable until after the last instruction of
>> every instance method. Period. This would basically equate to
>> placing an implicit reachability fence at all exist points of every
>> instance method (I.e. The equivalent of a try...finally). The "nice״
>> thing about such an implicit reachability fence is that it does not
>> really defeat any optimizations, as it only serves to extend the
>> lifetime of an oop (so potentially pressing slightly harder on the
>> register allocator). IMO this would auto-magically fix lots of
>> current rarely occurring bugs (like those on DBB, but also in user
>> code), and prevent many future ones.
>
> Mmmm.  That's what I said!
So we agree. At least for classes with finalizers in them. But since what you said was:

> … I have in the past argued that methods of classes with finalizers
> should automagically extend the lifetime of the "this" object.

And what I am saying is that ALL instance methods should have
this quality (not just the ones in classes with finalizers). We may still
have a gap (or maybe that gap is gone now).

My point is that this reachability race has nothing (specific) to do with
finalizers or finalization, and applies just as much to things that cannot
be easily detectable from a class's qualities (like having a finalizer).
Therefore any solution that only addresses finalizers seems insufficient.

> One other advantage to doing this
> automagically is that you won't get all these Java devs arguing about
> whether the reachabilityFence really was needed.

+1000.

I'd much prefer a language and JVM spec change, and a conservative
implementation that already applies that change in the meantime. It will
make current code "just work", and save us from a l lot of "your code
is bad, you misunderstood the promises of liveness on 'this', so it's your
fault, and you should fix your code with reachabilityFence" discussions.

Note that the ability to explicitly call reachabilityFence is still needed
elsewhere. probably in the places it was originally envisioned for. So
I'm not advocating for replacing it with implicit behavior, I'm arguing
for implementing both.


>
> Andrew.
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (859 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
In reply to this post by Gil Tene-2
On 12/09/2015 07:15 PM, Gil Tene wrote:

> Implementations can vary from an opaque non-inlineable method call
> that takes the 'this' ref as an argument, to ones that just maintain
> a USE on the exit paths that doesn't get optimized away (and as you
> note may mislead/drive the register allocator to want to keep the
> thing in a register), to ones that somehow eliminate the actual use
> and the wish to hold it in a register for that use, but prevent the
> recycling of the virtual register and/or associated stack slot.

Ah, okay, I think you're envisaging a much more major change to the
compiler than I was.  I can certainly see a way to do what you suggest
but it's a fair bit of work.

Andrew.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
In reply to this post by Vitaly Davidovich
On 12/09/2015 07:20 PM, Vitaly Davidovich wrote:
> I don't see how this extends the lifetime of the object unless, at minimum,
> you increment the counter at each operation where you want to extend the
> lifetime.

Yes, you do increment the counter at each operation.  There has to be
a use of the counter in the finalizer to keep it alive.  Thinking
about it some more though, even this may not be enough in the presence
of some very aggressive optimizations because there is no
happens-before relationship between the methods and the finalizer.

> And at this point, you may as well just stick
> reachabilityFence(this) inside the finalizer then.

Ummm, I don't understand this.

Andrew.
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
On 12/09/2015 07:51 PM, Andrew Haley wrote:

> On 12/09/2015 07:20 PM, Vitaly Davidovich wrote:
>> I don't see how this extends the lifetime of the object unless, at minimum,
>> you increment the counter at each operation where you want to extend the
>> lifetime.
>
> Yes, you do increment the counter at each operation.  There has to be
> a use of the counter in the finalizer to keep it alive.  Thinking
> about it some more though, even this may not be enough in the presence
> of some very aggressive optimizations because there is no
> happens-before relationship between the methods and the finalizer.

And without a fence there's nothing to stop the counter update
moving past the Unsafe operation.  So no, this won't really
work without at least a compiler barrier.

Andrew.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Andrew Haley
In reply to this post by Gil Tene-2
On 12/09/2015 07:30 PM, Gil Tene wrote:

>
>> On Dec 9, 2015, at 10:40 AM, Andrew Haley <[hidden email]> wrote:
>>
>> On 12/09/2015 05:53 PM, Gil Tene wrote:
>>
>>> My take on this would be to change the JLS and JVM spec to state
>>> that 'this' remains reachable until after the last instruction of
>>> every instance method. Period. This would basically equate to
>>> placing an implicit reachability fence at all exist points of every
>>> instance method (I.e. The equivalent of a try...finally). The "nice״
>>> thing about such an implicit reachability fence is that it does not
>>> really defeat any optimizations, as it only serves to extend the
>>> lifetime of an oop (so potentially pressing slightly harder on the
>>> register allocator). IMO this would auto-magically fix lots of
>>> current rarely occurring bugs (like those on DBB, but also in user
>>> code), and prevent many future ones.
>>
>> Mmmm.  That's what I said!
>
> So we agree. At least for classes with finalizers in them. But since what you said was:
>
>> … I have in the past argued that methods of classes with finalizers
>> should automagically extend the lifetime of the "this" object.
>
> And what I am saying is that ALL instance methods should have
> this quality (not just the ones in classes with finalizers). We may still
> have a gap (or maybe that gap is gone now).

Ah, yes we do.

> My point is that this reachability race has nothing (specific) to do with
> finalizers or finalization, and applies just as much to things that cannot
> be easily detectable from a class's qualities (like having a finalizer).
> Therefore any solution that only addresses finalizers seems insufficient.

Possibly so, yes, given that there is nothing special about "this".
I take your point.

What would this do to objects which don't escape?  I presume that
there would be no need to extend their lifetimes, and the usual
"as if" rule would apply.

Andrew.

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Andrew Haley
Yes, you do increment the counter at each operation.  There has to be
a use of the counter in the finalizer to keep it alive. 

Right, that's what I thought would need to happen, but then you made it sound like only finalizer actually does something.  So here you have a possible performance degradation ... 
 
Thinking about it some more though, even this may not be enough in the presence
of some very aggressive optimizations because there is no
happens-before relationship between the methods and the finalizer.

Yup, and that's why I said I doubt this even works.

Ummm, I don't understand this.

Before your clarification that counter is updated at each use, I was just saying that if counter is only used inside finalizer then you may as well just put reachabilityFence(this) in there.  In other words, if you had some reason to believe that simply using some field of the object inside the finalizer was sufficient, then rF(this) is just as good.  This is, of course, incorrect but that's what I meant.


On Wed, Dec 9, 2015 at 2:51 PM, Andrew Haley <[hidden email]> wrote:
On 12/09/2015 07:20 PM, Vitaly Davidovich wrote:
> I don't see how this extends the lifetime of the object unless, at minimum,
> you increment the counter at each operation where you want to extend the
> lifetime.

Yes, you do increment the counter at each operation.  There has to be
a use of the counter in the finalizer to keep it alive.  Thinking
about it some more though, even this may not be enough in the presence
of some very aggressive optimizations because there is no
happens-before relationship between the methods and the finalizer.

> And at this point, you may as well just stick
> reachabilityFence(this) inside the finalizer then.

Ummm, I don't understand this.

Andrew.


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Andrew Haley

sent from my phone
On Dec 9, 2015 3:36 PM, "Andrew Haley" <[hidden email]> wrote:
>
> On 12/09/2015 07:30 PM, Gil Tene wrote:
> >
> >> On Dec 9, 2015, at 10:40 AM, Andrew Haley <[hidden email]> wrote:
> >>
> >> On 12/09/2015 05:53 PM, Gil Tene wrote:
> >>
> >>> My take on this would be to change the JLS and JVM spec to state
> >>> that 'this' remains reachable until after the last instruction of
> >>> every instance method. Period. This would basically equate to
> >>> placing an implicit reachability fence at all exist points of every
> >>> instance method (I.e. The equivalent of a try...finally). The "nice״
> >>> thing about such an implicit reachability fence is that it does not
> >>> really defeat any optimizations, as it only serves to extend the
> >>> lifetime of an oop (so potentially pressing slightly harder on the
> >>> register allocator). IMO this would auto-magically fix lots of
> >>> current rarely occurring bugs (like those on DBB, but also in user
> >>> code), and prevent many future ones.
> >>
> >> Mmmm.  That's what I said!
> >
> > So we agree. At least for classes with finalizers in them. But since what you said was:
> >
> >> … I have in the past argued that methods of classes with finalizers
> >> should automagically extend the lifetime of the "this" object.
> >
> > And what I am saying is that ALL instance methods should have
> > this quality (not just the ones in classes with finalizers). We may still
> > have a gap (or maybe that gap is gone now).
>
> Ah, yes we do.
>
> > My point is that this reachability race has nothing (specific) to do with
> > finalizers or finalization, and applies just as much to things that cannot
> > be easily detectable from a class's qualities (like having a finalizer).
> > Therefore any solution that only addresses finalizers seems insufficient.
>
> Possibly so, yes, given that there is nothing special about "this".
> I take your point.
>
> What would this do to objects which don't escape?  I presume that
> there would be no need to extend their lifetimes, and the usual
> "as if" rule would apply.

Hopefully EA is not impacted by this - it certainly shouldn't be.  I can't immediately see a problem that this would present for EA purposes.

>
> Andrew.
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Chris Vest
In reply to this post by Andrew Haley
Even non-volatile writes can be scalability bottle-necks due to cache sloshing, even if you writing the same value every time.

We have a Page concept in Neo4j that, like DBB, has a raw pointer in a long field. However, we have too many of these objects for them to override finalize() - the associated companion objects would take up too much heap space - so they instead all reference a single object that when finalised will release all the native memory. Therefor special rules for objects with finalisers won't work for us. We also pull the native pointers out of these page objects, when working with the memory, because this is used in some of our hottest code and every indirection counts. So making instance methods keep the instance alive would only work because those places incidentally also have field references to the page objects.

Our code works because we need to guard the memory accesses with locks on the page objects, which keeps them alive. However, I wouldn't be surprised to hear about uses for fast explicit reachability fences.

Chris

> On 9. dec. 2015, at 20.03, Andrew Haley <[hidden email]> wrote:
>
> On 12/09/2015 06:52 PM, Vitaly Davidovich wrote:
>>>
>>> I don't think it'd be measurable.  A global volatile write is pretty
>>> cheap.  And I'm sure there are several such writes when queuing a
>>> finalizer.
>>
>>
>>> The global volatile gets hit once, when the object is finalized.  Not
>>> at every access, which is what you'd have to do with a compiler
>>> barrier.
>>
>> Perhaps I misunderstood your global volatile suggestion -- when is it
>> written to exactly? What's the usage?
>
> In the finalizer.  The idea is that you keep a counter in the
> object and then write it to a global when finalized.  I don't
> think this can be done much more cheaply without changes to
> the compiler, and it's certainly much cheaper than the current
> implementation of reachabilityFence.
>
> Andrew.
>
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

David Holmes-6
In reply to this post by Vitaly Davidovich

By having construction happen-before finalization, it ensures that if finalization happens after construction is complete then it will see all of the constructed values, even though they happened in a different thread. This is normal happens-before with regard to two synchronization actions – but a construction is not a synchronization action it was special-cased.

 

David

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Vitaly Davidovich
Sent: Thursday, December 10, 2015 1:36 AM
To: [hidden email]
Cc: [hidden email]
Subject: Re: [concurrency-interest] DirectByteBuffers and reachabilityFence

 

sent from my phone
On Dec 9, 2015 6:11 AM, "David Holmes" <[hidden email]> wrote:


>
> Andrew Haley writes:
> > On 09/12/15 09:21, David Holmes wrote:
> >
> > > The happens-before requirement was deliberately set the way it is to
> > > show that an object can not be finalized before its construction has
> > > completed (whether normally or abnormally). So I would agree with
> > > Justin that it should not be possible for an object to be finalized
> > > before construction has completed - regardless of potential compiler
> > > optimizations etc.
> >
> > Hmmm, okay.  It might be that I misremembered or perhaps it was a bug,
> > but I don't think so.  Is there really a happens-before relationship
> > between a constructor of an object with no volatile or final fields
> > and its finalizer?
>
> My recollection - and I've been trying to find this in the JavaMemoryModel
> archives - is that the happens-before between constructor and finalizer was
> introduced because the normal "trick" of using synchronization was very
> counter-intuitive in constructors given the object has not been published.
>
> That said, A happens-before B simply establishes visibility/ordering rules
> for the case when A occurs before B. It says nothing about B occurring
> before A, or B and A overlapping. Other mechanisms have to force the
> temporal order. So it may be I misspoke my support of Justin's position. :(

I have a different interpretation, akin to your previous answer.  There's very little point in stating that ctor happens-before finalization if that's not even the case always (i.e. they overlap or occur in reverse order) - how would that be meaningful?

>
> David
> -----
>
>
> > Andrew.
> > _______________________________________________
> > Concurrency-interest mailing list
> > [hidden email]
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by Chris Vest

sent from my phone
On Dec 9, 2015 3:50 PM, "Chris Vest" <[hidden email]> wrote:
>
> Even non-volatile writes can be scalability bottle-necks due to cache sloshing, even if you writing the same value every time.

Yup, this is just "fancy" false sharing.

>
> We have a Page concept in Neo4j that, like DBB, has a raw pointer in a long field. However, we have too many of these objects for them to override finalize() - the associated companion objects would take up too much heap space - so they instead all reference a single object that when finalised will release all the native memory. Therefor special rules for objects with finalisers won't work for us. We also pull the native pointers out of these page objects, when working with the memory, because this is used in some of our hottest code and every indirection counts. So making instance methods keep the instance alive would only work because those places incidentally also have field references to the page objects.
>
> Our code works because we need to guard the memory accesses with locks on the page objects, which keeps them alive. However, I wouldn't be surprised to hear about uses for fast explicit reachability fences.
>
> Chris
>
> > On 9. dec. 2015, at 20.03, Andrew Haley <[hidden email]> wrote:
> >
> > On 12/09/2015 06:52 PM, Vitaly Davidovich wrote:
> >>>
> >>> I don't think it'd be measurable.  A global volatile write is pretty
> >>> cheap.  And I'm sure there are several such writes when queuing a
> >>> finalizer.
> >>
> >>
> >>> The global volatile gets hit once, when the object is finalized.  Not
> >>> at every access, which is what you'd have to do with a compiler
> >>> barrier.
> >>
> >> Perhaps I misunderstood your global volatile suggestion -- when is it
> >> written to exactly? What's the usage?
> >
> > In the finalizer.  The idea is that you keep a counter in the
> > object and then write it to a global when finalized.  I don't
> > think this can be done much more cheaply without changes to
> > the compiler, and it's certainly much cheaper than the current
> > implementation of reachabilityFence.
> >
> > Andrew.
> >
> > _______________________________________________
> > Concurrency-interest mailing list
> > [hidden email]
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: DirectByteBuffers and reachabilityFence

Vitaly Davidovich
In reply to this post by David Holmes-6
Yes, I understand the meaning of happens-before.  My point, however, is that specifying things this way but not actually mandating that finalizer() runs after all load/store operations in the constructor have occurred is meaningless (and "hostile" towards developers) - it would be impossible to reason reliably about anything in the finalizer.

On Wed, Dec 9, 2015 at 3:51 PM, David Holmes <[hidden email]> wrote:

By having construction happen-before finalization, it ensures that if finalization happens after construction is complete then it will see all of the constructed values, even though they happened in a different thread. This is normal happens-before with regard to two synchronization actions – but a construction is not a synchronization action it was special-cased.

 

David

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Vitaly Davidovich
Sent: Thursday, December 10, 2015 1:36 AM
To: [hidden email]
Cc: [hidden email]
Subject: Re: [concurrency-interest] DirectByteBuffers and reachabilityFence

 

sent from my phone


On Dec 9, 2015 6:11 AM, "David Holmes" <[hidden email]> wrote:

>
> Andrew Haley writes:
> > On 09/12/15 09:21, David Holmes wrote:
> >
> > > The happens-before requirement was deliberately set the way it is to
> > > show that an object can not be finalized before its construction has
> > > completed (whether normally or abnormally). So I would agree with
> > > Justin that it should not be possible for an object to be finalized
> > > before construction has completed - regardless of potential compiler
> > > optimizations etc.
> >
> > Hmmm, okay.  It might be that I misremembered or perhaps it was a bug,
> > but I don't think so.  Is there really a happens-before relationship
> > between a constructor of an object with no volatile or final fields
> > and its finalizer?
>
> My recollection - and I've been trying to find this in the JavaMemoryModel
> archives - is that the happens-before between constructor and finalizer was
> introduced because the normal "trick" of using synchronization was very
> counter-intuitive in constructors given the object has not been published.
>
> That said, A happens-before B simply establishes visibility/ordering rules
> for the case when A occurs before B. It says nothing about B occurring
> before A, or B and A overlapping. Other mechanisms have to force the
> temporal order. So it may be I misspoke my support of Justin's position. :(

I have a different interpretation, akin to your previous answer.  There's very little point in stating that ctor happens-before finalization if that's not even the case always (i.e. they overlap or occur in reverse order) - how would that be meaningful?

>
> David
> -----
>
>
> > Andrew.
> > _______________________________________________
> > Concurrency-interest mailing list
> > [hidden email]
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
12345678