Hey Remi, Indeed - Uwe just beat you slightly to the punch. I'll need to play with it to see what "little slower" actually translates to :).
Thanks P.S. We've nicely sidetracked a bit from my original question, but I suppose the between-the-lines answer is that there's no plan to expose some of the guts of a direct buffer in a supported manner. On Thu, Feb 23, 2017 at 1:05 PM, Remi Forax <[email protected]> wrote: > Hi Vitaly, > I believe that what you are looking for is > MethodHandles.byteBufferViewVarHandle > [1] that creates a VarHandle that allows to do aligned/unaligned access on > a ByteBuffer. > It should be a little slower that using Unsafe because of the bound check > (and the nullcheck but it is usually removed by the VM). > That's said, unaligned access are faster with a VarHandle because > sun.misc.Unsafe (which is stuck in the Java 8 world unlinke > jdk.internal.misc.Unsafe) does not provide a way to do an unaligned access > so you have do multiple read which is slower. > > cheers, > Rémi > > http://download.java.net/java/jdk9/docs/api/java/lang/ > invoke/MethodHandles.html#byteBufferViewVarHandle-java. > lang.Class-java.nio.ByteOrder- > > ----- Mail original ----- > > De: "Vitaly Davidovich" <[email protected]> > > À: "Uwe Schindler" <[email protected]> > > Cc: "jigsaw-dev" <[email protected]> > > Envoyé: Jeudi 23 Février 2017 18:05:36 > > Objet: Re: sun.nio.ch.DirectBuffer and jdk9/jigsaw > > > On Thu, Feb 23, 2017 at 11:54 AM, Uwe Schindler <[email protected]> > > wrote: > > > >> Hi, > >> > >> Why do you need the address at all in the Java code? Java code can use > the > >> official ByteBuffer methods to access the memory you are wrapping. In > Java > >> 9 that’s optimized very good by Hotspot and should be almost as fast as > >> array accesses (we proved that in Apache Lucene - congrats to the > Hotspot > >> committers). If you need special access modes like volatile access, then > >> you can use Java 9's VarHandles. You can get a VarHandle to the backing > >> direct buffer using the MethodHandles API. > >> > > I mentioned this upthread - the base address is used for index > calculations > > to read/write data using Unsafe directly. I don't know about Java 9 as > > I've not tried it yet, but the generated assembly for using BB methods vs > > Unsafe did not favor BB. There are also various safety checks in > > DBB/Buffer internals that won't get optimized away. > > > > Also, my general experience with looking at C2 optimizations has led me > to > > the conclusion that the optimizations are "unstable" - innocent code > > changes, differences in order of how classes are loaded, differences in > > what callsites trigger compilation first, and a bunch of other otherwise > > benign things can interfere with inlining decisions, which is typically > the > > reason things go sideways in terms of optimization. > > > > As for MethodHandles and VarHandles, that's one possibility I'm > considering > > as a way to migrate off using DirectBuffer (although I'd still like to > know > > if there's any plan to standardize/formalize some notion of a direct > > buffer). However, my understanding is that using MH will still require > me > > to crack into jdk code (to get access to the DBB and friends) and thus > > require addExports. DirectBuffer is still accessible if using > addExports, > > but it's a wrinkle I was hoping to iron out, hence what started this > email > > chain. > > > >> > >> Uwe > >> > >> ----- > >> Uwe Schindler > >> [email protected] > >> ASF Member, Apache Lucene PMC / Committer > >> Bremen, Germany > >> http://lucene.apache.org/ > >> > >> > -----Original Message----- > >> > From: jigsaw-dev [mailto:[email protected]] On > Behalf > >> > Of Vitaly Davidovich > >> > Sent: Thursday, February 23, 2017 5:30 PM > >> > To: Chris Hegarty <[email protected]> > >> > Cc: jigsaw-dev <[email protected]> > >> > Subject: Re: sun.nio.ch.DirectBuffer and jdk9/jigsaw > >> > > >> > On Thu, Feb 23, 2017 at 11:10 AM, Chris Hegarty > >> > <[email protected]> > >> > wrote: > >> > > >> > > > >> > > > On 23 Feb 2017, at 11:30, Vitaly Davidovich <[email protected]> > >> wrote: > >> > > >> ... > >> > > > The buffers are reused by having them point to different native > >> memory > >> > > > block addresses; those blocks are managed by native code. As > >> > mentioned, > >> > > > the ByteBuffer (DirectByteBuffer concretely) is used as the Java > >> level > >> > > > interface/view of native memory, allowing Java and native code to > >> > > > communicate. > >> > > > >> > > So a DBB, under your code, may report a different address at some > time > >> > > in the future, to that of what it currently reports? > >> > > >> > Correct. > >> > > >> > > I was not aware of this > >> > > usecase. Is any similar code available on the web, or elsewhere, so > we > >> > > could try to determine why this is being done? > >> > > > >> > Unfortunately it's not open source code, and I don't immediately know > of > >> > anything similar on the web (or otherwise). However, the gist is the > >> > following: > >> > 1) Allocate a 0-size DBB (i.e. ByteBuffer.allocateDirect(0)). This > gives > >> > you a Java "handle", if you will, to some native memory. But, since > this > >> > DBB will be attached/reattached to different memory dynamically, > there's > >> no > >> > need for an actual allocation. > >> > 2) Native code wants to expose a segment of memory to Java. In JNI, > it > >> > sets the address and capacity of this DBB to the pointer where the > native > >> > memory segment starts, and to the capacity (it knows how big the > native > >> > segment is). Java code asks for this DBB to be "attached" to, say, > some > >> > sort of message, and the JNI/native code perform these functions. > >> > 3) Java gets the attached DBB back, and can then use its API > >> > (getXXX/setXXX) to read/write that native block. Once the operation > >> > completes, the DBB is recycled for reuse (i.e. can be attached to a > >> > different native segment again). > >> > > >> > Obviously, we can use > >> > http://docs.oracle.com/javase/8/docs/technotes/guides/jni/ > spec/functions > >> . > >> > html#GetDirectBufferAddress > >> > to get the address and then expose that via a JNI helper - in fact, > >> that's > >> > what was done before. But, there's a JNI call penalty here for what > is > >> > otherwise a memory read. DirectBuffer::address() solves that nicely, > and > >> > also plays well with the C2 JIT (as mentioned) because the callsites > >> where > >> > this is used only see DBB, and then the whole invokeinterface call is > >> > devirtualized and inlined into a quick type check and Java field read > - > >> the > >> > performance of this is, as you can imagine, significantly better than > the > >> > JNI approach. > >> > > >> > If you think of what a DBB really is, it's pretty much what it's name > >> > suggests - it's an API to read/write to native memory, rather than > Java > >> > heap memory (i.e. HeapByteBuffer). But, there's no reason the native > >> > memory backing the DBB has to also be allocated via Unsafe itself, > >> although > >> > that's the more common scenario. > >> > > >> > On the Java side, consumers of this have a common and conventional API > >> > over > >> > a byte buffer, i.e. ByteBuffer, which can optionally be used in the > >> manner > >> > above (obviously callers will need to know what mode they're using). > >> > > >> > > >> > > -Chris. > >> > > > >> > > > >> >
