RFR  8148117: Move sun.misc.Cleaner to jdk.internal.ref
uschindler at apache.org
Sat Jan 23 20:01:05 UTC 2016
> Here's a question for you: could you tolerate a closeable mapped
> ByteBuffer which was somewhat slower to access? It is hard to make a
> secure closeable mapped ByteBuffer: the question is how small the
> overhead of closeability can be made.
Lucene uses the ByteBuffer like a conventional byte arrays and expects as close performance to that as possible. In Java 7 and Java 8 there is for sure some large overhead because of missing Hotspot optimizations. In Java 9 we found out, that recent builds are now almost as fast as byte access. Completely destroying that improvement would be no good. :-(
We are also looking into using VarHandles instead of ByteBuffers directly (using the new MethodHandles methods to get a VarHandle on top of any ByteBuffer, although this does not really fit our use-case completely, because we cannot use views like long on top of a ByteBuffer, because we sometimes also need unaligned accesses). We will try to check this out as soon as first builds with VarHandles are available. Of course this would also not help, if a Closeable ByteBuffer would also slowdown the VarHandle accesses.
> But if the answer is "We can't tolerate *any* additional overhead, no
> matter how small" then there is no motivation to do any experiments.
It depends how small! If the speed is still somewhere between Java 8 ByteBuffer performance and the recent Hotspot improvements in Java 9, I agree with trying it out. But some volatile memory access on every access is a no-go. The code around ByteBufferIndexInput in Lucene is the most performance-critical critical code, because on every search query or sorting there is all the work happening in there (millions of iterations with positional ByteBuffer.get* calls). As ByteBuffers are limited to 2 GiB, we also need lots of hairy code to work around that limitation!
If you look at ByteBufferIndexInput's code you will see that we simply do stuff like trying to read from one bytebuffer and only if we catch an BufferUnderflowException we fall back to handling buffer switches: Instead of checking bounds on every access, we have fallback code only happening on exceptions. E.g. if you are 3 bytes before end of one buffer slice and read a long, it will throw BufferUnderflow. When this happens the code will fall back to read byte by byte from 2 different buffers and reassemble the long): https://goo.gl/g1jKcm Stuff like sorting will make heavy use of the ByteBufferIndexInput's (RandomAccessIndexInput interface's) methods like readXxx(long position) for stuff like quicksort with really hundreds of millions of items!
More information about the core-libs-dev