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

Freezing sometimes in glfw and opengl native methods. #490

Closed
Alex----- opened this issue Aug 2, 2019 · 14 comments
Closed

Freezing sometimes in glfw and opengl native methods. #490

Alex----- opened this issue Aug 2, 2019 · 14 comments

Comments

@Alex-----
Copy link

  • LWJGL version: 3.2.2 release build 10 and 3.2.3 snapshot build 8. 3.2.1 release build 12 does not have the bug.
  • Java version: tested openjdk 11 and 12
  • Platform: tested windows 8.1 and windows 10
  • Module: glfw, opengl

My thread is freezing for about a second sometimes in native glfw and opengl methods (Have seen it happen for glfwSwapBuffers, glfwPostEmptyEvent, glDrawArrays, and glUseProgram). The rate that it freezes at changes, but may be related to the number of native method calls (It freezes every other second on one screen of my app but goes for around 10 seconds without freezing in another, where less is drawn).

@Spasi
Copy link
Member

Spasi commented Aug 3, 2019

Hey @Alex-----,

There's not enough information to be able to reproduce this. It would be simpler if you could prepare an MCVE that exhibits the same behavior.

It also sounds unlikely that this is an issue with LWJGL or GLFW. Have you tried logging GCs and seeing if there's a correlation with the freezing?

@Alex-----
Copy link
Author

I just tried logging GCs and there is one logged right after it unfreezes each time:
[226.217s][info][gc] GC(231) Pause Young (Normal) (GCLocker Initiated GC) 358M->349M(800M) 0.468ms

@Alex-----
Copy link
Author

There are no freezes when using -XX:+UseShenandoahGC and adoptopenjdk jdk-12.0.2+10 (windows x64), There are freezes with G1GC and ConcMarkSweepGC.

@Spasi
Copy link
Member

Spasi commented Aug 3, 2019

Sounds like a GC issue then, which depends on how many allocations are happening in your application. You are not the first person to report bad performance with G1GC.

It's weird that you mention a difference between 3.2.1 and newer versions though, there haven't been any changes in LWJGL that would cause higher allocation rates. Also, LWJGL never passes objects between Java and native code, so the choice of GC algorithm doesn't affect the performance of LWJGL bindings.

Does the issue get (much) worse if you run with -XX:-DoEscapeAnalysis? Also, what's the behavior like with -XX:+UseParallelGC and -XX:+UnlockExperimentalVMOptions -XX:+UseZGC?

@Alex-----
Copy link
Author

ParallelGC is also freezing, -XX:-DoEscapeAnalysis does not affect it very much, it might be freezing a bit less. ZGC is not supported.

@Alex-----
Copy link
Author

I'm calling glfwWaitEventsTimeout(1) in a loop from the main thread and changing it to glfwWaitEventsTimeout(0.01) stops the freezing. I think it's using a JavaCritical jni function which blocks the GC until it returns.

@Spasi
Copy link
Member

Spasi commented Aug 4, 2019

Does the freezing stop with -XX:-CriticalJNINatives?

@Alex-----
Copy link
Author

Yes

@Spasi Spasi added the Type: Bug label Aug 5, 2019
LWJGL-CI pushed a commit to LWJGL-CI/lwjgl3 that referenced this issue Aug 17, 2019
Will be restored in LWJGL 3.3 with the possibility to enable it at
runtime, if the JVM can avoid excessive blocking (e.g. using
ShenandoahGC).
@Spasi
Copy link
Member

Spasi commented Aug 17, 2019

Hey @Alex-----,

I spent several days trying different approaches, but in the end decided that supporting critical JNI natives is too risky for the time being. The next LWJGL 3.2.3 snapshot will support standard JNI only and you shouldn't see any more freezing. A major change is coming in LWJGL 3.3 that will make it possible to enable JNI crits at runtime, when it is appropriate (e.g. when the Shenandoah GC is enabled).

The root of the problem is this line in the JDK code. The work behind check_needs_gc_for_critical_native is done in all critical native functions. I had made the wrong assumption that there would not be any GC interactions in functions with primitive-only arguments (the vast majority of LWJGL functions). That's why a function like glfwWaitEvents ends up blocking the GC (and eventually freezing your application).

Btw, the only GCs that return true from supports_object_pinning() are Shenandoah (can pin the region that holds the object) and Epsilon (n/a).

@shipilev, sorry to bother you, but I think you may be interested. I understand that critical natives are not officially supported, but they could be made very useful, at least until the release of Project Panama. Specifically:

  • Shouldn't the above code be checking if the critical native function actually has array parameters? Isn't it pointless to lock the GC when there are no array parameters? This would allow GCs that do not support object pinning to skip the lock.
  • I noticed that the !Universe::heap()->supports_object_pinning() check exists only in the x86_64 implementation. Shouldn't it be added to the other implementations as well?

And a couple more, on the off chance you actually have time to look into this:

  • Other than the GC lock, would it be possible to skip more work in the wrapper of critical JNI functions with primitive-only parameters & return values? Random examples: thread state transition, memory barrier, safepoint poll. Reminder: critical JNI functions cannot call back into the JVM and do not interact with the heap in any way.
  • JNI method call overhead is significantly higher since Java 10. Testing with a JNI function that does nothing, JMH benchmarks suggest that the overhead has increased from ~6ns on Java 8 to ~8-9ns on Java 10 (testing on a Ryzen 1800X). Java 9 is also slower than 8, but marginally so, maybe a CPU cycle or two. Java 11+ or alternative GCs make no difference. Do you maybe know what happened?

@shipilev
Copy link

@Spasi: I forwarded your questions to shenandoah-dev here: https://mail.openjdk.java.net/pipermail/shenandoah-dev/2019-August/010419.html

@gudenau
Copy link
Contributor

gudenau commented Jul 5, 2021

I'm curious, is there a way to use critical JNI calls now? It has been a while and it was stated in here that there would be a configuration option for that.

@Spasi
Copy link
Member

Spasi commented Jul 6, 2021

Hey @gudenau, LWJGL does not currently support CriticalJNINatives.

It's in my plans to do some more testing with JDK-8233343, which should eliminate freezing and yield lower overhead (no thread transitions). However, any support for critical JNI would necessarily have to be limited to specific JVM configurations (16+ or pre-16 with ShenandoahGC enabled). I'm not sure it's worth the trouble, with Project Panama so close to release.

Supporting both crit and non-crit JNI bindings so far meant a lot of complexity and much larger native binaries. My plan was to introduce runtime binding generation (i.e. building shared libraries at runtime with something like TinyCC), which would not only eliminate the duplication, but also entire artifacts (e.g. OpenGL) and the horrible org.lwjgl.system.JNI class. However, we now support macOS/Windows ARM64 and there are requests for even more platforms, which complicates things. It's not easy to find a JIT compiler in a small package that won't limit what platforms/architectures we can support. We can't possibly ship LWJGL with something like LLVM, it's massive and would defeat the purpose.

@gudenau
Copy link
Contributor

gudenau commented Jul 6, 2021

Fair enough!

I do have some experience with the foreign linker and memory APIs, they are pretty nice to use. For now they are a bit slower than plain old JNI, but I do have hope for them in the next few Java releases.

@ice1000
Copy link

ice1000 commented May 7, 2023

Will lwjgl3 be moved to Java 16+?

fayer3 pushed a commit to fayer3/lwjgl3 that referenced this issue Jul 14, 2023
Will be restored in LWJGL 3.3 with the possibility to enable it at
runtime, if the JVM can avoid excessive blocking (e.g. using
ShenandoahGC).
This issue was closed.
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

5 participants