Sharing experience with FFM API and jextract

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Oct 17 17:33:50 UTC 2025


Hi Zoran, thanks for the feedback! Some comments inline below

On 17/10/2025 18:14, Zoran Sevarac wrote:
> Hi all,
>
> I want to share our experience and some benchmark results using FFM 
> API and jextract in Deep Netts.
>
> We've used jextract to generate bindings for CUDA libraries to create 
> a replacement for JCUDA  that was previously used, and here are some 
> observations (note that we didn't generate entire API just a subset 
> that we needed)
>
> What we liked:
> 1. Generating bindings using jextract is pretty straightforward.  It 
> requires a bit of experimentation and practice to figure out available 
> options  and the best configuration.
> 2. We actually didn't have to write any binding code, everything was 
> generated, and it will be easy to regenerate for a new version when 
> required.
>
> Performance and benchmarking
> We benchmarked 100 iterations of image classification using VGGNet 
> convolutional neural network:
> 1. We got the same performance as with JNI (used by JCuda).
> 2. Nearly same performance as PyTorch (Python and C)
> 3. Java 25 performed significantly better and more stable than Java 
> 22, while running the benchmark.
> Java 25, required only one warmup iteration after which results were 
> stable, and had significantly lower variation overall, while Java 22 
> required up to 40 warmup iterations to stabilize, and had large 
> variations  (up to 8x).
> So difference in stability between Java 22 and 25 is huge (at least 
> for our use case)
I'm glad that you got reasonable performance out of it, and that you 
noticed the jump from 22 to 25. A lot of polishing has happened behind 
the curtain to make warmup faster (and more is to come :-) ).
>
> Few observations
> 1. Enums are mapped to functions. It would make more sense if they 
> could be Java enums.

See:

https://git.openjdk.org/jextract/pull/284

It is a tricky topic, hopefully that PR summarizes the main reasons as 
to why that isn't the slamdunk it seems it is...

> 2. Code for dependent libraries was duplicated  for each library if it 
> was in a different package. The solution for us was to put all 
> generated bindings/classes in a single package.

Yep. With jextract filtering you can at least generate different 
libraries in different packages though. Have you tried that?

https://github.com/openjdk/jextract/blob/master/doc/GUIDE.md#filtering

> 3. Binding for C types are duplicated for each .h file/generated 
> class. Would be cleaner if these are generated on only one shared place
Yep -- this is an open issue that we'd like to address. It is also 
problematic for JDK adoption. Likely at some point it will be possible 
to include/exclude these as well.
> 4. Generated API will always require a layer on top of it. It strictly 
> corresponds to native API style, for C with pointers/MemorySegments 
> and status code returns.
This is sort of by design. Jextract is intended to give you usable 
bindings that do not require direct use of method handles/var handles, 
but that introduce the least amount possible (none virtually) of 
performance overhead. The task of making bindings hgher-level is a lot 
more creative, and requires good taste in applying and coupling language 
features with API design so as to achieve optimal balance for users. A 
tool can generate _one_ opinionated high-level API. But there are as 
many opinionated APIs as there are users (see your comments on enums :-) 
), so the only principled choice here is sticking to the C API.
> 5. Jextract is available only in version 22 (and based on JDK22), 
> which can add confusion which version to use for which version of Java 
> https://jdk.java.net/jextract/

This is confusing I agree. We plan to ship 25 binaries soon, and we'll 
try to make sure the versions don't diverge too much in the future

Thanks

Maurizio



More information about the panama-dev mailing list