【问题标题】:JavaFX 8 QuantumRenderer high CPU usageJavaFX 8 QuantumRenderer 高 CPU 使用率
【发布时间】:2017-11-14 18:08:53
【问题描述】:

我有一个 JavaFX APP,其中包含两个列表视图,显示从我的服务器收到的传入客户订单(使用自定义单元工厂)。我还有一些表格视图显示来自 Postgres 数据库的信息(这分布在选项卡窗格内的几个选项卡中)。 用户必须接受订单(通过单击它),并在文本框中输入一些信息。

该应用程序最初是使用 Java7 编写和部署的。我没有任何问题。 但最近我决定切换到 Java8。我修改了我的代码以使用 lambda,并在应用程序中添加了一些额外的东西:

  • 在文本流中每分钟检查和显示订单状态的时间线;
  • 修改 customcellfactory 类以使用外部 CSS,使用 setId 代替 setStyle;
  • ...

现在,应用程序运行良好,但在正常运行 2-3 小时后,它变得迟缓。由于我很难模拟分析器中的行为,因此我使用了 jstack top -H,并将 pidnid 匹配以找出发生了什么。

这样我发现罪魁祸首是QuantumRenderer,CPU使用率超过95%:

  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)

运行应用程序的机器使用的是 64 位版本的 Lubuntu。

我不知道应该去哪里找出问题所在...

【问题讨论】:

  • @gontard 唉,就我而言,没有。但是我有一个相当大的Graph,现在我设法将其缩小(提供更少的数据点)。关于 OP,我不知道。
  • @gontard 在我的情况下,问题是图形硬件加速。有一个解决方法:切换到软件渲染并禁用 vsync:java -jar -Dprism.order=sw -Dprism.vsync=false my_app.jar
  • 我也看到了同样的问题。也需要几个小时才能显现。我在 com.sun.prism.es2.X11GLDrawable.swapBuffers(X11GLDrawable.java:50) 看到最后两个调用在 com.sun.prism.es2.X11GLDrawable.nSwapBuffers(Native Method) 的 QuantumRenderer-0 (X11GLDrawable.java:50) 我试过 - DPrism.order 以及 -DPrisim.force,都无济于事。我确实有一个 GPU,而 JAvaFX 确实说它支持 3D。这是 Prism 中的错误吗?
  • 这个bug好像是相关的:bugs.openjdk.java.net/browse/JDK-8088984

标签: javafx cpu renderer


【解决方案1】:

您的渲染器似乎正在使用 X11 管道(Java2D?),这可能是导致 CPU 使用率高(软件加速)的原因。你的显卡支持硬件加速吗?

尝试使用-Dprism.verbose=true 获取更多信息,如果您的显卡确实支持硬件加速,您可能想尝试使用-Dprism.forceGPU=true 强制它,也可以尝试使用 -Dprism.order=es2,es1,sw,j2d 启用 OpenGL 管道以提高 Java2D 性能(您也可以尝试使用旧的 Java2D 标志 -Dsun.java2d.opengl=true 但我认为这不会影响棱镜)。

我还建议查看 OpenJFX performance tips and tricks checklist 我已经看到节点中的 CPU 使用率很高,使用任何类型的动画时使用 Node.setCache(true) 及其 CacheHints缺点是这会占用更多内存)。

另外,看看您是如何从工作线程更新 UI 的。在 FX UI 线程中做最少的工作并正确更新它非常重要,并且仅在必要时查看this other question 以了解有关 javafx.concurrent.Task 类及其的更多信息正确使用从工作线程更新 UI。

这看起来更像是一个软件加速问题,Dprism.verbose 应该让您了解更多,但遵循其他建议永远不会有坏处!希望这会有所帮助!

【讨论】:

  • 好吧,你错了:使用软件加速实际上解决了我的问题。
  • 很高兴您解决了您的问题!我不确定我可能会“出错”,因为我建议其中的多项内容使用 prism.order 在渲染顺序中添加软件加速。如果您通过其他标志或操作解决了这个问题,请添加您的答案,以便每个人都可以从准确的响应中受益。
  • 感谢您的意见。我说你搞错了,我指的是你说问题可能是软件加速引起的,而事实上,在你回复前一个月的评论中,我说禁用硬件加速可以解决问题。不幸的是,这个解决方案只不过是一种解决方法......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 2021-12-09
  • 2014-07-16
  • 2014-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多