Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX 8 QuantumRenderer high CPU usage

I have a JavaFX APP containing two listviews displaying incoming customer orders (using a custom cellfactory) received from my server. I also have a few tableview displaying information from a Postgres database (this are spread across a few tabs inside a tabpane). The user has to take an order (by clicking on it), and enter a few information inside textboxes.

The application was initially written an deployed using Java7. I had no problem whatsoever. But recently I decided to switch to Java8. I modified my code to use lambdas and added a few extras stuff to the app:

  • a timeline to check and display orders status every minute, inside a textflow;
  • modified the customcellfactory class to use an external CSS, with setId instead of setStyle;
  • ...

Now, the application is running fine but, after 2-3 hours of uptime it becomes sluggish. Since is hard for me simulate the behavior inside a profiler I used jstack, top -H, and matching pid with nid to find out what is happening.

This way I found out that the culprit was QuantumRenderer with 95+% CPU usage:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
30300 utilizat+  20   0 5801608 527412  39696 S  95,1  6,5  60:57.34 java

"QuantumRenderer-0" #9 daemon prio=5 os_prio=0 tid=0x00007f4f182bb800 nid=0x765c runnable [0x00007f4eeb2a1000]
   java.lang.Thread.State: RUNNABLE
    at com.sun.prism.es2.X11GLDrawable.nSwapBuffers(Native Method)
    at com.sun.prism.es2.X11GLDrawable.swapBuffers(X11GLDrawable.java:50)
    at com.sun.prism.es2.ES2SwapChain.present(ES2SwapChain.java:186)
    at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:107)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
    at java.lang.Thread.run(Thread.java:745)

The machine running the application is using a 64Bit version of Lubuntu.

I can't figure out where should I look to find out what is the problem...

like image 866
Lucian Avatar asked Sep 18 '14 06:09

Lucian


1 Answers

It seems your renderer is using the X11 pipeline (Java2D?) which could be the cause of high CPU usage (software acceleration). Does your graphics card supports hardware acceleration?

Try getting more information with -Dprism.verbose=true if your graphics card does support hardware acceleration you might want to try to force it with -Dprism.forceGPU=true, also try enabling the OpenGL pipeline to increase Java2D performance with -Dprism.order=es2,es1,sw,j2d (you could also try with the old Java2D flag -Dsun.java2d.opengl=true but I think that won't affect prism).

I would also recommend taking a look at the OpenJFX performance tips and tricks checklist I've seen high CPU usage in nodes that was somewhat fixed with the usage of Node.setCache(true) and its CacheHints when using any kind of animation (with the downside that this uses more memory).

Also, take a look at how you are updating your UI from your worker threads. It's important to do minimum work in the FX UI Thread and update it from your workers correctly and only when necessary, take a look at this other question to learn more about the javafx.concurrent.Task class and its correct usage to update the UI from worker threads.

This seems much more like a software acceleration issue and Dprism.verbose should let you know more but following the other suggestions never hurts! Hope this helps!

like image 193
JavierJ Avatar answered Sep 27 '22 23:09

JavierJ