JavaFX动画 - 性能逐渐下降

4
我创建了一个包含多个文本节点的动画。用户应该在从服务器接收到文本时阅读它。问题是,在几分钟内(大约5分钟),性能开始下降。从60 fps降至30 fps及以下。因此,文本很难阅读。
编辑2:
我创建了一个最小、完整和可验证的示例:
项目中有3个文件:
MainFxApp:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.util.List;

public class MainFxApp extends Application {

    @Override
    public void start(Stage primaryStage) {

        Pane root = new Pane();
        root.setStyle("-fx-background-color: black;");

        MyAnimationTimer myAnimationTimer = new MyAnimationTimer((List<MyText>) (List<?>) root.getChildren());

        MyText newText;
        for (int i = 65; i < 85; i++) {
            newText = new MyText("" + ((char) i));
            newText.setFill(Color.GREEN);
            newText.setFont(Font.font(40));
            myAnimationTimer.addNode(newText);
        }

        Scene scene = new Scene(root, 1200, 600);

        primaryStage.setTitle("Performance test");
        primaryStage.setScene(scene);
        primaryStage.show();

        myAnimationTimer.start();


    }

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

我的动画计时器:

import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.scene.CacheHint;
import javafx.scene.Node;

import java.util.List;

public class MyAnimationTimer extends AnimationTimer {
    private List<MyText> nodes;
    private double panelWidth;
    private double panelHeight;
    private double basicVelocity; // Distance per nanosecond

    private long lastFrameTime;

    private long timeCount = 0;
    private int frameCount = 0;

    MyAnimationTimer(List<MyText> nodes) {
        super();
        this.nodes = nodes;
        this.panelWidth = 1200;
        this.panelHeight = 600;
        this.setBasicVelocity();
    }

    @Override
    public void start() {
        this.lastFrameTime = System.nanoTime();
        super.start();
    }

    @Override
    public void handle(long now) {

        long deltaT = now - lastFrameTime;
        double deltaX = this.basicVelocity * deltaT;

        for (MyText node : this.nodes) {
            node.setTranslateX(node.getTranslateX() + node.direction * deltaX);
            if (node.getTranslateX() < 0) {
                node.direction = 1;
            } else if (node.getTranslateX() > 1200) {
                node.direction = -1;
            }
        }

        this.lastFrameTime = now;

        this.timeCount += deltaT;
        this.frameCount++;

        if (timeCount > 1000000000) {
            System.out.println(this.frameCount / (double) timeCount * 1000000000);
            this.frameCount = 0;
            this.timeCount = 0;
        }
    }

    void addNode(final MyText node) {  // Not sure about the final thing
        Platform.runLater(() -> {
            node.setCache(true);
            node.setCacheHint(CacheHint.SPEED);
            node.setTranslateY(panelHeight / 2);

            double nodePositionX = panelWidth - 20;

            if (nodes.size() >= 1) {
                Node lastNode = nodes.get(nodes.size() - 1);
                double lastNodeEnd = lastNode.getTranslateX() + 50;
                if (lastNodeEnd > nodePositionX) {
                    nodePositionX = lastNodeEnd;
                }
            }

            node.setTranslateX(nodePositionX);

            nodes.add(node);
        });
    }

    private void setBasicVelocity() {
        Platform.runLater(() -> {
            this.basicVelocity = ((panelWidth / 4) * 3 / (double) 5000 / 1000000.0);
        });
    }
}

我的文本:

import javafx.scene.text.Font;
import javafx.scene.text.Text;

class MyText extends Text {
    int direction = -1;

    MyText(String text) {
        super(text);
        this.setFont(new Font("Arial Regular", 40));
    }
}

即使是这个简单的例子,性能下降也非常明显。场景中有20个节点,FPS下降到20以下。我的CPU是i5-4440 CPU(3.10GHz × 4)。无论我在哪个平台上测试它 - JavaFX 8、JavaFX 9和Ubuntu 16.04,问题都会出现。
编辑3:
该问题似乎只存在于Linux平台上。
然而,即使在Windows上,当我通过Platform.runLater方法频繁访问JavaFX线程时,动画似乎也不太流畅,尽管它保持在60fps。有人知道如何改进吗?
谢谢,Jan

我的 MyText 类在哪里? - SedJ601
你能在资源监视器中看到任何资源被消耗了吗?你使用的是什么操作系统? - Itai
抱歉回复晚了,我不在这一周。我编辑中添加了MyText源代码。我正在使用Ubuntu 16.04,但我也在Windows 10上测试过代码,并获得了相同的结果。该问题发生在JavaFX 8和JavaFX 9上。当我启动应用程序时,动画以60 fps运行,CPU消耗大约为4个线程的20%。当出现问题时,每个线程使用的大约是50%,因此CPU时间消耗的增加是显着的。 - Jan Beneš
我已经尝试了您的示例,无法复现该问题,也没有发现明显的内存泄漏等问题。我会让应用程序运行一段时间,并在性能问题发生时进行报告。(Win 10,i5-4300U 2.50GHz)。CPU使用率约为1.5%。使用jdk_1.8.0_60构建。 - d.j.brown
我又在Windows 10上尝试了一遍,似乎仍然保持在60fps。我无法解释为什么,但是我再也无法在Windows上复现这个问题了。然而,在Linux上的问题仍然存在,并且我已经在每次测试中都复现了它。 - Jan Beneš
1
内存消耗也会增加吗?您可以使用-Dprism.verbose=true运行吗?另外,请查看此问题:https://dev59.com/2Zvga4cB1Zd3GeqP9OkZ#40239829 - Itai
1个回答

1
似乎您的Linux硬件加速在JavaFX渲染方面存在一些问题。我的机器具有类似的功能,没有性能问题。
尝试仅以软件模式运行您的代码:
java -Dprism.order=j2d -jar myfxapp.jar 

在这种情况下,它可能是这个的副本:https://dev59.com/2Zvga4cB1Zd3GeqP9OkZ#40239829 - Itai
它确实解决了问题,而且它确实是@sillyfly发布的帖子的重复。我将标记它为这样。谢谢。 - Jan Beneš

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接