Использование высокопроизводительного процессора QuantumRenderer для JavaFX 8
У меня есть приложение JavaFX, содержащее два списка, отображающих входящие заказы клиентов (с использованием пользовательской cellfactory), полученные с моего сервера. У меня также есть несколько таблиц, отображающих информацию из базы данных Postgres (это распространяется на несколько вкладок внутри вкладки).
Пользователь должен сделать заказ (щелкнув по нему) и ввести несколько информации внутри текстовых полей.
Вначале приложение было развернуто с использованием Java7. У меня не было никаких проблем.
Но недавно я решил переключиться на Java8. Я изменил свой код, чтобы использовать lambdas, и добавил в приложение несколько дополнительных материалов:
- временную шкалу для проверки и отображения состояния заказов каждую минуту, внутри текстового потока;
- изменил класс customcellfactory для использования внешнего CSS, с setId вместо setStyle;
- ...
Теперь приложение работает нормально, но после 2-3 часов работы он становится вялым. Поскольку мне сложно моделировать поведение внутри профилировщика, я использовал jstack, top -H
и сопоставлял pid
с nid
, чтобы узнать, что происходит.
Таким образом, я узнал, что виновником было QuantumRenderer
с 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)
Аппарат, запускающий приложение, использует версию Lubuntu версии 64Bit.
Я не могу понять, где я должен искать, в чем проблема...
Ответы
Ответ 1
Кажется, ваш рендерер использует конвейер X11 (Java2D?), который может быть причиной высокого использования ЦП (ускорение программного обеспечения). Поддерживает ли ваша видеокарта аппаратное ускорение?
Попробуйте получить дополнительную информацию с помощью -Dprism.verbose=true
, если ваша графическая карта поддерживает аппаратное ускорение, которое вы, возможно, захотите попытаться заставить с помощью -Dprism.forceGPU=true
, также попробуйте включить конвейер OpenGL для повышения производительности Java2D с помощью
-Dprism.order=es2,es1,sw,j2d
(вы также можете попробуйте со старым флагом Java2D
-Dsun.java2d.opengl=true
, но я думаю, что это не повлияет на призму).
Я также рекомендовал бы взглянуть на контрольный список производительности и трюков OpenJFX Я видел высокую загрузку процессора в узлах, которые были несколько исправлено с использованием Node.setCache(true) и CacheHints при использовании какой-либо анимации (с недостатком, что это использует больше памяти).
Кроме того, посмотрите, как вы обновляете свой пользовательский интерфейс из своих рабочих потоков. Очень важно выполнять минимальную работу в потоке FX UI и правильно обновлять его от ваших работников и только при необходимости взглянуть на этот другой вопрос, чтобы узнать больше о javafx.concurrent.Task и его правильное использование для обновления пользовательского интерфейса от рабочих потоков.
Это похоже на проблему с программным ускорением, и Dprism.verbose должен дать вам знать больше, но после других предложений никогда не бывает больно! Надеюсь, это поможет!