Merged
Conversation
TODO - chase down memory leak - cleanup
Java (and Kotlin) have to autobox things to use the generic uniffi FFI converter (since generics require boxed values). This technically makes for a super strange series of calls for uniffi calls: `long→Long→Long→long→FFI→long→Long→Long→long` for a primitive add call for example. From my benchmarking (after making these changes) it looks like the JIT is already optimizing those extra calls away, but this changes makes it more correct by default instead of depending on the JIT always figuring the right thing out.
|
Minimum allowed coverage is Generated by 🐒 cobertura-action against a0c0339 |
- close() vs GC race doesn't mess things up under contention with the backpressure cleaner - Arena\.global() memory stability (may come back to this one after thinking on global more) - renabled the testsprites fixture from forever ago - REUSABLE_STATUS segment zeroing doesn't corrupt error data between calls
Which removes the known small memory leak. Benches showed there isn't a significant performance impact.
This hasn't been tested on a real Android device, but if it doesn't work for someone we can deal with it then.
giarc3
approved these changes
Apr 2, 2026
README.md
Outdated
|
|
||
| * Java 20+: `javac`, and `jar` | ||
| * The [Java Native Access](https://github.com/java-native-access/jna#download) JAR downloaded and its path added to your `$CLASSPATH` environment variable. | ||
| * Java 21+: `javac`, and `jar` |
Member
Author
There was a problem hiding this comment.
I think the current shape of the FFM API is actually available in 21+, it left preview in 22+. PanamaPort lists 22+ for the Android support part though, so might as well list that as well.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Benchmarks using the new upstream benches show a marked improvement, see below the fold.
Major changes:
Libraryinterface withMethodHandlelookups. Every native function has a staticMH_*field with its function descriptor.RustBufferswitched from a JNAStructureto an FFMMemorySegment-backed typeuniffiRustCallhelpers useMemorySegmentas well. Also added primitive-specialized versions to avoid a long boxing/unboxing chain (which didn't change performance due to JIT in tested cases, but is "more correct")Linker.nativeLinker().upcallStub(), so do callback interfacesObjectCleanerHelperhad a major change. The FFM was much faster than JNA and the some of the benches that create objects effectively blitzed objects because of it. The static cleaner reaper couldn't keep up and the benches would OOM. I confirmed that with a unit test (and that it failed before the fix). The fix was to introduce backpressure to the cleaner and have it opportunistically drain when registering something new with the cleaner. It seemed to have a side effect of improving performance due to more consistent memory use (I was expecting a small hit).This probably puts the nail in the coffin of #23, since it requires Java 22 and make some major changes around FFM compatibility.
Java FFM vs JNA Speedup
function-calls
callbacks
On some things like trait-interfaces there is significant variation due to GC pressure, the lows that seem to be more normal cases are ~250-500ns.