Kristoffer Sjögren wrote:
Ah, I overlooked that flag. This means I can return the pointer to Java and write directly into LMDB for the duration of the current transaction. Sadly, after trying it, there is no noticeable effect on latency. Commits are still occupying majority of total time.
Could be some kind of overhead calling JNI repeatably in a tight loop? So instead I tried to batch all 1 million addresses over to JNI in one go and manage puts+begin+commit from the C side. Again, this did not have much notable effect.
What's even more weird is that when I clock the batch time from C I get around 1.8 - 1.7 sec, but the total execution time is actually more like 6 sec! Clearly there is something I don't understand here.
Dunno what's going on there. Have you tried first with a smaller batch, 500K, 100K?
For reads I already let pass the value pointer to Java and read directly from it (like you suggest) and this part is actually ~1.5 times faster than the buffer copy approach in lmdbjni. Just to be sure, are the value pointers managed by LMDB or do I need to free them manually per transaction? Right now I just read data from them.
All pointers returned from LMDB are owned/managed by LMDB. That's already stated in the docs.
BTW, forgot to say thanks for a great product Howard!
On Sun, Jun 29, 2014 at 4:56 PM, Howard Chu <hyc@symas.com mailto:hyc@symas.com> wrote:
Kristoffer Sjögren wrote: Hi I'm experimenting a bit with developing a JNI library for LMDB that utilize zero copy buffers. As you may know there is a project called lmdbjni [1] already but it does buffer copy only. I must admit that my C and JNI skills is not really that great, so please forgive any stupidity on my part. Can't offer much advice on java or JNI. But your test doesn't really leverage LMDB's zero-copy writes. To do that you have to use the MDB_RESERVE write flag before generating the output value. Otherwise there's still a copy from the mdb_put argument into the actual DB. I don't know what other buffer copies occur before you finally reach mdb_put, but I don't see why you need to do anything special to pass a user value into mdb_put. zero-copy really only has significant benefit for readers, and that's where you have to play games with non-GC'd pointers. Perhaps other java users on this list can offer more advice. Anyway, i'm taking the sun.misc.Unsafe (no bounds checking) approach for memory allocation and pass memory addresses through JNI to LMDB for both writes and reads and at the moment I have implemented put, get, begin, commit [2].