[11] RFR : java.nio.Buffer attachments

David Lloyd david.lloyd at redhat.com
Fri Mar 9 16:51:42 UTC 2018


On Fri, Mar 9, 2018 at 10:00 AM, Alan Bateman <Alan.Bateman at oracle.com> wrote:
> On 09/03/2018 15:23, David Lloyd wrote:
>>
>> I was just wondering if anyone has had a chance to give this a look
>> and a think.  Thanks!
>>
> I think this needs a compelling example to demonstrate the motivation.
> Changing ByteBuffer duplicate to run arbitrary code to create a new
> attachment object for the new buffer is one thing that I found a bit strange
> in the proposal.

The interesting thing about giving an attachment the chance to react
to view creation is that it allows an implementation to track how many
outstanding views there are of a given buffer.  This in turn could
allow for (for example) implementations which reference-count the
backing buffer, and even "smart" pooling allocators which can
intelligently split large buffers into small buffers, or coalesce
adjacent small buffers into larger buffers.  A buffer pool
implementation which requires each view to be freed could even allow
unused regions to be reallocated as smaller buffers.

It also provides an opportunity for a variety of useful leak and error
detection debug modes.  Given an implementation which only allows
freeing of the "original" pooled buffer, it would be simple to add a
debugging mode where detailed information about invalid frees could be
logged, e.g. "An attempt was made to free a view of buffer xyz; the
buffer was allocated at Blah.java:1234 and the view was created at
Blah.java:4567".  The entire duplication history of a particular
buffer could in fact be tracked and reported.  This kind of thing
would have been quite useful to me on more than one occasion.

> Reading your original mail, it wasn't clear to me how
> different this is to maintaining a maps buffers to object, or buffer to
> buffer pool. Do you have such a map today?

We've tried a number of approaches with varying degrees of success,
but all central pool management structures (including maps or queues)
have tended to be subject to observable contention.  We tend to use
various striping strategies to try to mitigate this, but in the end
thread-local caching has been the best solution so far.  However it is
necessary that it be possible to get information about the poolability
of a buffer from the buffer instance itself for thread-local caching
to really be effective, otherwise we're back to centralized contention
again.  Using a map efficiently in conjunction with thread-local
caching is fairly difficult AFAICT.  Direct attachment is really hard
to beat when associating one object with another, in terms of both
storage and access efficiency, as well as simplicity.  In the
simple/common case - where we would only be tracking and freeing the
"root" buffer - direct attachment should be much faster than using a
map, and the implementation is relatively simple as well.

A map would necessarily be keyed by the buffer instance.  This
requires employment of an identity-based concurrent hash map, due to
ByteBuffer's content-dependent equals/hashCode implementation; since
there isn't one in the JDK public API, this is something else that
must be produced or acquired by users.

It is not possible to track buffer views using a central map (or any
other way, AFAICT) without introducing a hook into view creation.

-- 
- DML


More information about the nio-dev mailing list