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:
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
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...
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!