tweag/inline-java

Document the performance cost of local/global refs creation

mboes opened this issue · 2 comments

mboes commented

The JNI defines two types of object references: local references (only valid in the current thread, dies at the end of current call frame) and global references (globally valid, GC controlled lifetime).

The jvm package, like jni, currently always creates local references. But objects with local references are hard to handle: need to make sure they don't get shared with other threads, and need to make sure the local reference gets discarded eventually (i.e. doesn't leak). Types might help dealing with local references safely, but this can have a big impact on API's and on the ease of writing bindings. Global references have a major advantage: we can treat global object like any other Haskell value: create it, and then largely don't worry about its lifetime (the GC will take care of it).

We could in theory create global references always, removing the local references handed to us by default by the JNI. Is this viable? It depends on the performance cost. If there are no performance implications, then there is great value in forgetting about local references altogether (no impact on API's, no lifetimes to worry about...). If the performance gap between local and global references is noticeable but not too large, then it may still be worth it to create global references by default and then optimize them away in special cases.

tl;dr: designing a proper solution to #7 requires data. Which design point is the best compromise will depend on the data.

The analysis of this issue needs to consider the effect of delegating to the Haskell GC the disposal of global references.

By now we have experienced in practice that the Haskell GC has no pressure to collect global references when the Java heap needs it urgently.

The benchmarks show that creating 200 local references takes as long as doing a method call with JNI. 10 global references with attached finalizers can be created in the same time. Maybe in some scenario where the workloads and the GC passes can be coordinated, global references would be an option. But it doesn't look clearly as the best default.

@mboes, do you want to explore any other alternatives? We could close the ticket otherwise.