1

I'm trying to figure out the best way to pass large amounts (20Kb - 2MB) of data from C++ to Java on Android. I'm using Djinni to generate as much of the bridge code as possible. The options I'm considering are:

  1. Use AHardwareBuffer - looks like an abstraction around shared memory and is intended primarily for EGL images, and other GLES/Vulkan rendering needs but could be used here. I'm uneasy because of the word "hardware" here as I'm not interfacing with hardware. Perhaps "hardware" just implies this memory can be safely mapped to a device and my use case is also ok? This solution would require hand coding some JNI code.

  2. Have Java provide the buffer - If java passes C++ bytes[] the data isn’t copied, only the address of the array. This is clunky as Java has to first ask C++ how big the buffer should be before allocating it. This solution could use auto-generated JNI code.

  3. Use NewDirectByteBuffer / java.nio.ByteBuffer.allocateDirect - Sources, without citations, claim that this is a bad option as its hard to manage and performs poorly for small amounts of data. It is what Google recommends though. This solution would require hand coding some JNI code.

I'm leaning towards option #2 as it doesn't require handwriting any JNI code and seems "good enough". I'm also assuming that this approach would work well in reverse (i.e. no/low overhead sharing of a buffer from Java to C++). Hoping to get y'alls thoughts here before prototyping/benchmarking as doing so will be a somewhat sizable investment.

Josh A.
  • 374
  • 3
  • 15
  • 3
    Why not just an array of bytes? Why complicate things? You don't need to pass the array from Java to C, just have C create the array. Worrying about a single memcopy is really premature optimization. – Gabe Sechan Apr 11 '22 at 20:35
  • 1
    I have to agree with @GabeSechan: keep it simple and use `byte` arrays. `public native byte [] getDataFromNativeCode(...);` You make it more complicated only ***after*** profiling your code proves the copying of data into the Java `byte[]` is a bottleneck. And guess what? There's a good chance your "improved" code won't be any faster. See https://stackoverflow.com/questions/26603285/return-byte-array-in-jni-android – Andrew Henle Apr 11 '22 at 23:01
  • I'm not worried about the CPU cycles necessary to do the memcpy, I'm worried about the extra memory usage. Based on these responses, I am relaxing my approach a bit. However, I've been reading the JNI spec and I'm struggling to find what types are guaranteed to be copied (or not). – Josh A. Apr 12 '22 at 02:45

1 Answers1

0

Snap's Djinni has built-in support for passing large buffers with and without ownership semantics. Checkout this link for details:

https://github.com/Snapchat/djinni#exposing-data-across-language-boundary-with-dataview

finalpatch
  • 26
  • 2
  • 1
    I'm still using the original Dropbox Djinni like a dummy. I'll upgrade to this as it totally solves my problem. Thanks. – Josh A. Jun 14 '22 at 21:51