Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Java array parameters #175

Closed
Spasi opened this issue Apr 1, 2016 · 11 comments
Closed

Add support for Java array parameters #175

Spasi opened this issue Apr 1, 2016 · 11 comments

Comments

@Spasi
Copy link
Member

Spasi commented Apr 1, 2016

The Hotspot JVM has an undocumented feature called Critical Natives, details here. It makes Java primitive arrays a viable alternative to NIO buffers and is a good match for LWJGL (virtually all JNI methods qualify, by design).

Pros:

  • Normal object lifecycle vs malloc/free or sun.misc.Cleaner
  • array[i] = array[j] vs buffer.put(i, buffer.get(j))
  • Computation on array -> pass to JNI vs computation on POJO -> copy to buffer -> pass to JNI

Cons:

  • Bigger natives
  • Bigger JAR
  • Hotspot only

Questions:

  • How does AutoSize work with arrays?
@Spasi Spasi added this to the 3.0.x milestone Apr 1, 2016
@ShadowLordAlpha
Copy link

I would love to have this as it would make the java and c look basically identical though it is undocumented and for internal use from what I see so it could change at any time especially with jigsaw coming in 9.

Another con you forgot is that its a JDK 7 feature.

I think it would also be good to see if they actually do speed anything up so a benchmark with a few functions first or something.

@octylFractal
Copy link
Contributor

Maybe it could be a secondary artifact, for those who know users will run on Hotspot JDK 7+ (e.g. they provide it) and want to get more speed. I could see that being very interesting for video games that bundle the JRE.

@kappaOne
Copy link
Member

kappaOne commented Apr 2, 2016

This looks like an awesome feature to have and would really allow clean looking LWJGL code (without the horrid NIO buffers).

Maybe LWJGL could have methods (or a utility class) that accept primitive arrays and where not supported (pretty rare situation IMO), automatically copying it to a buffer and using the buffer version of that API. Would allow users to use standard java arrays everywhere without worrying too much about compatibility.

@Spasi
Copy link
Member Author

Spasi commented Apr 2, 2016

I think it would also be good to see if they actually do speed anything up so a benchmark with a few functions first or something.

I've actually been testing it for the last couple of days. Got incredibly excited at first, because it sounded like it would improve all JNI methods, even methods that don't use arrays. Results:

  • There is indeed a benefit when doing Java-side computations and passing the array to JNI without a copy. We tested JOML code for this. The alternatives, calc on FloatBuffer or calc on POJO+copy to FloatBuffer, were slower.
  • There is absolutely no benefit to primitive-only JNI methods. Critical Natives do indeed skip some setup overhead in the JNI wrapper, but it's no more than 1-2 CPU cycles (measured with JMH).
  • Critical Natives are only used in a few crypto methods in the JDK, so they have been tuned for exactly that use-case (passing Java arrays). I figured it could get better, so I hacked JDK 9 and produced a build that removes even more stuff from the JNI wrappers. That gave real benefits even for the primitive-only case (for a no-arg method: 9.1ns down to 5.6ns per call). That was just an experiment, I don't think it's worth pushing for something like it, since Project Panama is coming in JDK 10.

Another con you forgot is that its a JDK 7 feature.

Maybe it could be a secondary artifact, for those who know users will run on Hotspot JDK 7+

Honestly, I still hate it that LWJGL needs to be Java 6 compatible. If it were up to me, it would support Java 8 and up. Even Android supports Java 8 now. Maybe open this discussion again before the 3.0.0 release?

Maybe LWJGL could have methods (or a utility class) that accept primitive arrays and where not supported (pretty rare situation IMO), automatically copying it to a buffer and using the buffer version of that API. Would allow users to use standard java arrays everywhere without worrying too much about compatibility.

Technically possible, but would be too much code for very few (if any) users.

@httpdigest
Copy link
Member

I am quite interested in this, too. Just to make sure that I would not invest time needlessly into JOML redesigning/extending it to make use of Java arrays, I would like to gather some benchmark results from users interested in using JOML with LWJGL 3.
I created a small JMH benchmark project here: https://github.com/JOML-CI/joml-bench
I would request for anyone interested to just download and run the prebuilt jar file and post their results into this GitHub issue.
You don't have to mention your hardware stats, and also not the exact numbers if you don't want to. Just which test performed better. Higher numbers (ops/s) are better.

@erodozer
Copy link

erodozer commented Apr 3, 2016

I don't think it's worth pushing for something like it, since Project Panama is coming in JDK 10

If you're worried about JNI wrappers and performance, have you looked into depending on JNA. It looks like what Panama is going to be based around, and it would provide a compatible solution for older JVMs even after 10 comes out.

@httpdigest
Copy link
Member

JNA is slower than using handwritten/generated JNI. JNA just allows bridging Java and native without writing native code ourselves. And that comes at a price, because the lowest denominator is just JNI. Everything wanting to bridge between Java and native has to use JNI. JNA simply has its own "hub" JNI dispatcher function and we pay the price for having JNA store the call arguments in its own data structure. Yes, it uses FFI, but that also adds to runtime.

@erodozer
Copy link

erodozer commented Apr 3, 2016

Ah, so does Panama's goal more or less provide what JNA's interface does, but skips the JNI step? If that's the case that'd be amazing.

Bundling a JRE with your app on desktop isn't uncommon, and is more than not recommended, especially if your app is distributed on Steam. I wonder how these changes would effect people who are trying to release apps on PS4/Xbox. I don't know what the distribution requirements are and if they have a specific requirement of what JVM to use or package. I'm afraid something like this could prevent developers from pushing their apps to those platforms if this is a change that can't be optional.

@Spasi
Copy link
Member Author

Spasi commented Apr 3, 2016

but skips the JNI step? If that's the case that'd be amazing.

Yes and a lot more. The current prototype can even generate inline assembly using pure Java.

I'm afraid something like this could prevent developers from pushing their apps to those platforms if this is a change that can't be optional.

Using array parameters will work on any JVM. If a JVM doesn't support Critical Natives, the only difference will be a performance penalty when using such methods.

@Spasi
Copy link
Member Author

Spasi commented Apr 22, 2016

An initial implementation is available in the array-params branch.

@Spasi Spasi closed this as completed in d06ec4a Apr 24, 2016
@Spasi
Copy link
Member Author

Spasi commented Apr 24, 2016

Support for Hotspot Critical Natives is now available in LWJGL 3.0.0 build 77.

The current implementation does not include byte[] array overloads. They would have low usefulness and would result in a massive number of new overloads. If you have an interesting use-case for byte arrays, please post here. It would be possible to generate byte[] overloads for specific functions only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants