gpt4 book ai didi

JavaFX FPS 上限为 60 FPS

转载 作者:行者123 更新时间:2023-11-30 06:10:57 33 4
gpt4 key购买 nike

JavaFX UI 线程上限为每秒 60 次更新(12)似乎是一种共识。据我了解,更新意味着 pulse

A pulse is an event that indicates to the JavaFX scene graph that it is time to synchronize the state of the elements on the scene graph with Prism. A pulse is throttled at 60 frames per second (fps) maximum and is fired whenever animations are running on the scene graph. Even when animation is not running, a pulse is scheduled when something in the scene graph is changed. For example, if a position of a button is changed, a pulse is scheduled.

来源:https://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm

为了弄清楚如果对 Platform.runLater 的调用超过 60 次会发生什么,我编写了这个小程序:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class HighUITraffic extends Application {

private int counter = 0;
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) {


StackPane root = new StackPane();


Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
long sheduleTime = System.currentTimeMillis();
System.out.println("Task "+counter+" run at "+sdf.format(new Date(sheduleTime)));
Platform.runLater(new RunInUI(counter));
counter++;
}
};
timer.schedule(task, 0, 10); // every 10ms => 100 per second

Scene scene = new Scene(root, 300, 250);

primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
private static class RunInUI implements Runnable {
private final int counter;

public RunInUI(int counter) {
this.counter = counter;
}

@Override
public void run() {
long executionTime = System.currentTimeMillis();
System.out.println("Task "+counter+" executed in Application Thread at "+sdf.format(new Date(executionTime)));
}
}
}

我的期望是:

  • Runnable被堆叠起来,UI线程穿插运行,然后执行所有排队的Runable
  • UI 线程执行前 60 个调用,然后将进一步的 Runable 排队。

然而,在 Runables 排队并由 UI 线程一次处理所有初始延迟后发生的事情是,这两个线程按顺序运行:

Task 1281 run at 2016-01-25T18:37:00.269 Task 1281 executed in Application Thread at 2016-01-25T18:37:00.269 Task 1282 run at 2016-01-25T18:37:00.274 Task 1282 executed in Application Thread at 2016-01-25T18:37:00.274 Task 1283 run at 2016-01-25T18:37:00.279

并且在一秒钟内有超过 60 个线程的调用(我尝试了 100 和 200,没有任何区别)。

所以我很困惑:

  • 我是否误解了以 60 个脉冲为上限的概念?
  • 这个小的执行片段不会太重,以至于可能会超过限制吗?

我首先想知道的是,如果线程已达到其上限限制,推送到 UI 线程的 Runable 会发生什么情况。是所有已排队的 Runable 在 UI 线程的一次运行中按顺序执行,还是只有一个 Runable 执行而其余的必须等待?第二种情况会导致严重的问题,当在 UI 线程上连续推送超过该限制的 Runable 时。

最佳答案

脉冲上限为 60fps。提交给 FX 应用程序线程的 Runnable 不是。

据我了解,有两个线程:FX 应用程序线程和棱镜渲染线程。 FX 应用程序线程使用队列中的 Runnable 并执行它们。 prism 渲染线程每秒最多执行 60 次,与 FX Application Thread 同步(从而暂时阻止它执行新的 runnable)并渲染帧,然后释放 FX Application Thread。

因此,FX Application Thread 会尽快执行您的Runnable,并且不限于每 1/60 秒执行一个 runnable;但它不会在帧渲染期间从队列中获取新的可运行对象。 (用户事件在 FX 应用程序线程上以类似于您发布的 Runnable 的方式处理。)

所以有几种方法可以让坏事发生。一种是在 FX 应用程序线程(无论是在事件处理程序中还是在 Runnable 中发布到 Platform.runLater())上执行需要很长时间的代码。这样做会阻止 Prism 渲染线程与 FX 应用程序线程同步,这意味着在可运行对象完成之前无法渲染下一帧。另一种方法是用过多的 Runnable 轰炸 FX 应用程序线程,这样队列的增长速度快于它们的消耗速度。 (本质上,由于队列总是有可用的东西,因此 FX 应用程序线程在这些情况下会变成繁忙的线程,并且不能保证 prism 渲染线程能够运行。)

因此,对您的问题的直接回答是 Runnable 按照它们发布的顺序执行,尽可能迅速地在单个线程上执行。上限为 60 fps 的帧渲染将暂时停止使用队列中的 Runnable

在伪代码中,我猜测(这只是我对它如何工作的直觉,这不是基于源代码)FX 应用程序线程看起来像 p>

while (fxToolkitRunning()) {
Runnable runnable = runnableQueue.take(); // block until something available
acquireLock();
runnable.run();
releaseLock();
}

棱镜渲染线程看起来像这样:

while (fxToolkitRunning()) {
while (! timeForNextFrame()) {
sleep(timeUntilNextFrame());
}
acquireFXApplicationThreadLock();
if (sceneNeedsUpdating()) {
renderFrame();
}
releaseFXApplicationThreadLock();
}

关于JavaFX FPS 上限为 60 FPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34999121/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com