简体   繁体   中英

JNA Native.setXXX() slow

Not sure if this is the right place to ask. I noticed in YourKit (but any other profiler will do) huge contributions by Native.setShort, in my case. This sets fields in a Structure in order to fill jna library call arguments. SetShort is called some 10 levels underneath the jna lib proxy call. The actual function call to windows' kernel32.dll does not appear in the sampling at all. Neither does any Structure.read activity when returning the values.

Now, I looked at what this and the other primitive value setters do: they take the address of the argument and move sizeof( argument) bytes to the target adress by memcpy or bcopy, possibly surrounded by try/catch macros. Why is done? Why not just something like:

*((short*) target) = value

Would this be more efficient or is the try/catch important here? The surrounding PSTART/PEND macros seem to not always generate a try/catch. This is the most recent JNA grab 4.2.0 from git.

Update: It looks like this was the profiler playing a practical joke on me. Today I saw the wasted time more evenly spread among other call stack levels from and to the actual native call.

My solution was to use JNA direct mapping: Add another function in my own DLL on top of the OS API, that takes primitive pointers instead of a Structure.ByReference to return values. Calling this function with a one-element primitive array for each return parameter took 370 ns vs 1500 ns (exluding new Structure.ByReference() ).

So, in the end, Native.setXXX() methods really are slow, together with all the glue code around JNA method invocations. But JNA direct mapping does it. I have never tested actual JNI calls, so cannot compare timings here.

On *nix systems, PSTART / PEND do a setjmp / longjmp to trap a range of memory faults (but only if Native.setProtected(true) ). On Windows, it uses structured exception handling (basically try / catch ) to do the same thing, and is on by default.

Even when enabled, it's unlikely they would add much overhead compared to the overhead of the JNI transition itself (going from Java to C or vice versa).

Generally, passing a Structure to native code is not terribly efficient, since the automatic writes and reads depend heavily on reflection to copy Java fields into native memory. In most cases, though, it doesn't really matter.

For those few cases where you find a bottleneck, you'd want to use JNA's direct mapping and restrict yourself to primitive arguments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM