If you're using very large structures and using them often, here's a
tip that can boost performance by several orders of magnitude. Note
that you should follow this tip *only* if you really need the
performance boost; otherwise you may wind up obfuscating your code.
By default, when JNA makes a native call it will copy the full
contents of a Java Structure to native memory prior to the call and
read it all back after the call. If your Structure is very large,
this can result in significant overhead reflecting all the fields of
the Structure. The reflection dwarfs the actual native communication
time.
If you're only reading or writing a single field, it's much faster
(although somewhat less elegant) to use the readField(String) and
writeField(String,Object) methods to access the data, while disabling
the normal read and write. Depending on the size of your structure,
you may see two orders of magnitude or more improvement in the native
function call time.
Here's an example of performing the same operation two different ways:
class Big extends Structure {
public int toNative;
public int fromNative;
// lots more fields, the more, the bigger difference in performance
}
class FastBig extends Big {
public void read() { }
public void write() { }
}
Big big = new Big();
big.toNative = 42;
lib.callMyNativeFunction(big);
System.out.println("Got " + big.fromNative);
Big fast = new FastBig();
fast.writeField("toNative", 42);
lib.callMyNativeFunction(fast);
System.out.println("Got " + fast.readField("fromNative"));
If you wrap a loop and time these, you'll see what kind of difference
it makes. On a test structure with 25 "int" fields, the fast version
reduces time by a factor of 10.
Trivia: some other "struct" implementations (e.g. Javalution) use
objects for all fields and require an explicit "write" or "set" on
each. This reduces data transfor and/or reflection overhead, at the
expense of simplicity of assignment and initialization.
JNA:
s.field = 1;
call(s.field);
Javalution:
s.field.set(1);
call(s.field.get());