JavaFX动画 - 性能恶化[重复]

Posted

技术标签:

【中文标题】JavaFX动画 - 性能恶化[重复]【英文标题】:JavaFX animation - deteriorating performance [duplicate] 【发布时间】:2017-12-04 17:39:39 【问题描述】:

我创建了多个文本节点的动画。用户应该正在阅读从服务器接收到的文本。问题是几分钟(大约 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,它也似乎并不流畅。有人知道如何改进吗?

谢谢,杨

【问题讨论】:

MyText 类在哪里? 您能看到资源监视器中消耗的任何资源吗?您使用的是什么操作系统? 对于我已经离开一周的迟到的回复,我深表歉意。我在编辑中添加了 MyText 源代码。我使用的是 Ubuntu 16.04,但我也在 Windows 10 上测试了代码,结果相同。 JavaFX 8 和 JavaFX 9 都出现此问题。当我启动应用程序时,动画以 60 fps 运行,所有 4 个线程的 CPU 消耗约为 20%。当问题发生时,每个线程的使用量大约为 50%,因此 CPU 时间消耗会显着增加。 我已经尝试了您的示例,但无法重现该问题,也看不到任何明显的问题,例如内存泄漏。如果出现性能问题,我将让应用程序运行一段时间并报告。 (Win 10,i5-4300U 2.50GHz)。 CPU 使用率 ~ 1.5%。使用 jdk_1.8.0_60 构建 内存消耗是否也增加了?你可以用-Dprism.verbose=true 运行吗?另外,看看这个问题:***.com/questions/40228866/… 【参考方案1】:

看起来您的 Linux 硬件加速在 JavaFX 渲染方面存在一些问题。我在具有类似功能的机器上没有遇到性能问题。

尝试在纯软件模式下运行您的代码:

java -Dprism.order=j2d -jar myfxapp.jar 

【讨论】:

在这种情况下,它可能与此重复:***.com/questions/40228866/… 它确实解决了这个问题,它确实是@sillyfly 发布的线程的副本,我将这样标记它。谢谢

以上是关于JavaFX动画 - 性能恶化[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用JAVAFX和SWING有啥区别[重复]

即使在eclipse中安装javafx后我也无法运行javafx程序[重复]

找不到javafx.controls JavaFX 11 / JDK 11.0.1 [重复]

使用数字-Javafx [重复]

JavaFX不会连接到MYSQL [重复]

JAVAFX:未设置位置错误[重复]