jextract looses type safety in generated bindings
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Apr 7 13:43:08 UTC 2021
On 07/04/2021 11:57, Maurizio Cimadamore wrote:
> If the latter, we had an API similar to that in an earlier iteration
> of the Panama project (another Pointer-like API); while this API was
> enough, from an expressiveness perspective, to support jextract use
> cases, it also added noticeable overhead to basic operation like
> pointer dereference.
To give a better ideas of the numbers involved - there is a nice native
interop shootout here:
https://github.com/zakgof/java-native-benchmark
This was ran against the old Panama API, the one featuring the
high-level Pointer API. As you can see Panama doesn't come out too well
in that benchmark.
For fun, I've ported the benchmark using the API we have released in
Java 16, and here are the results I have:
```
Benchmark Mode Cnt Score Error Units
JmhCallOnly.bridj avgt 50 279.563 ▒
4.312 ns/op
JmhCallOnly.jna avgt 50 826.049 ▒
11.840 ns/op
JmhCallOnly.jna_direct avgt 50 934.675 ▒
13.662 ns/op
JmhCallOnly.jni_javacpp avgt 50 36.899 ▒
0.618 ns/op
JmhCallOnly.jnr avgt 50 233.757 ▒
3.090 ns/op
JmhCallOnly.panama avgt 50 30.332 ▒
0.386 ns/op
JmhGetSystemTimeSeconds.bridj avgt 50 1306.806 ▒
131.925 ns/op
JmhGetSystemTimeSeconds.java_calendar avgt 50 136.437 ▒
3.949 ns/op
JmhGetSystemTimeSeconds.java_date avgt 50 50.450 ▒
0.750 ns/op
JmhGetSystemTimeSeconds.java_localdatetime avgt 50 58.232 ▒
1.456 ns/op
JmhGetSystemTimeSeconds.jna avgt 50 3194.622 ▒
216.633 ns/op
JmhGetSystemTimeSeconds.jnaDirect avgt 50 3227.971 ▒
193.953 ns/op
JmhGetSystemTimeSeconds.jni_javacpp avgt 50 418.683 ▒
5.789 ns/op
JmhGetSystemTimeSeconds.jnr avgt 50 327.486 ▒
7.548 ns/op
JmhGetSystemTimeSeconds.panama avgt 50 390.615 ▒
3.987 ns/op
```
(all this has been ran unscientifically, using a VirtualBox instance :-) )
As you can see, the API we have in 16 are pretty competitive with JNI -
only JNR does better, but I believe that's due to differences in how
memory is allocated - e.g. the memory segment API does a malloc and a
free, and it also zeroes memory (as well as keeping track of how much
memory has been allocated in the JDK as a whole, which is a need for
us). I'm pretty sure that (a) JNR doesn't bother with any of this
(rightfully so!) and (b) if we started playing with custom segment
allocators (which the latest API allows you to do) we can obtain numbers
which surpass everything seen here (as we can amortize the allocation cost).
When it comes to overhead for a single native call (e.g. ignoring memory
allocation overhead), you can see that the Linker API in 16 comes out
the best of the bunch.
So, every interop solution in this space picks a different compromise
when it comes to expressiveness vs. performance. You can see how our
APIs have benefited by going lower level - we started off being the
slowest and ended up there with the best (there is some 10x gain in
there). Of course users are free to pick the solution they prefer,
depending on the particular use cases they are facing.
Maurizio
More information about the panama-dev
mailing list