21

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

Floern
  • 33,559
  • 24
  • 104
  • 119
Lucian
  • 236
  • 2
  • 8
  • could it be related to http://stackoverflow.com/questions/10607507/javafx-2-blank-label-refresh-issue ? – gontard Jun 08 '15 at 12:22
  • @gontard Alas, in my case, no. But I have a quite large `Graph` which I now managed to make smaller (give less data points). About the OP, I don't know. – glglgl Jun 08 '15 at 15:58
  • 2
    @gontard In my case the problem was the graphics hardware acceleration. There is a workaround: switching to software rendering and disabling vsync: **java -jar -Dprism.order=sw -Dprism.vsync=false my_app.jar** – Lucian Jun 14 '15 at 19:32
  • 1
    I, too, am seeing this same issue. It also takes several hours to manifest. I see a QuantumRenderer-0 wit6h the last two calls being at com.sun.prism.es2.X11GLDrawable.nSwapBuffers(Native Method) at com.sun.prism.es2.X11GLDrawable.swapBuffers(X11GLDrawable.java:50) I tried -DPrism.order as well as -DPrisim.force, both to no avail. I do have a GPU and JAvaFX does say it supports 3D. Is this a bug in Prism? – Walt Corey Feb 19 '16 at 20:02
  • This bug seems to be related: https://bugs.openjdk.java.net/browse/JDK-8088984 – Lucian Feb 21 '16 at 15:45

1 Answers1

5

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!

Community
  • 1
  • 1
JavierJ
  • 539
  • 5
  • 13
  • Well, you got it wrong: using software acceleration actually solves my problem. – Lucian Feb 21 '16 at 15:46
  • 2
    Glad you solved your problem! I'm not sure what I could "got wrong" since I suggested multiple things among them adding software acceleration in the rendering order with prism.order. If you solved this with other flags or actions please add your answer so everyone can benefit from an exact response. – JavierJ Feb 22 '16 at 16:15
  • Thank you for your input. When I said that you got it wrong I was referring to the fact that, you suggested that the problem might be caused by software acceleration, when, in fact, in a comment made a month before your reply, I stated that disabling hardware acceleration solves the problem. Unfortunately this solution is nothing more than a workaround... – Lucian Feb 23 '16 at 21:51