JavaFx动画性能不佳,占用了我所有的CPU

时间:2014-10-23 20:29:15

标签: performance animation javafx-2 javafx-8

我写了以下演示程序。 每个包含一个Text节点的四个HBox将添加到根(组)中。第一个和最后一个是动画的时间轴,以交换他们的位置。 所有的HBox都具有相同的CSS风格。

结果是“每秒帧数”非常低的动画。 我有一个双核E7400 2.8Ghz Cpu。一个核心100%使用。我期望计算在GPU中完成。 删除大部分CSS(特别是阴影效果)后,动画变得更加平滑。 在我有更好的表现的同时,为了保持视觉效果,我能做些什么吗? 使用css来装饰要设置动画的节点是不是一种不好的做法?

我还使用-Dprism.verbose = true来检查硬件加速是否打开。一切似乎都没问题

Prism pipeline init order: d3d sw
Using platform text rasterizer
Using native-based Pisces rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.d3d.D3DPipeline
Loading D3D native library ...
        succeeded.
D3DPipelineManager: Created D3D9 device
Direct3D initialization succeeded
(X) Got class = class com.sun.prism.d3d.D3DPipeline
Initialized prism pipeline: com.sun.prism.d3d.D3DPipeline
Maximum supported texture size: 8192
Maximum texture size clamped to 4096
OS Information:
        Windows 7 build 7601
D3D Driver Information:
    ATI Radeon HD 4800 Series
    \\.\DISPLAY1
    Driver aticfx32.dll, version 8.17.10.1129
    Pixel Shader version 3.0
    Device : ven_1002, dev_9440, subsys_0502174B
    Max Multisamples supported: 4
 vsync: true vpipe: true
Loading Prism common native library ...
        succeeded.

这是程序

public class Sample extends Application{

    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();
        Card card1 = new Card(1);
        Card card2 = new Card(2);
        Card card3 = new Card(3);
        Card card4 = new Card(3);
        card1.relocate(100, 200);
        card2.relocate(250, 200);
        card3.relocate(400, 200);
        card4.relocate(550, 200);
        root.getChildren().add(card1);
        root.getChildren().add(card2);
        root.getChildren().add(card3);
        root.getChildren().add(card4);
        primaryStage.setScene(new Scene(root , 800, 600, Color.DARKSLATEGREY));
        primaryStage.show();

        Timeline tl = new Timeline(new KeyFrame(
                Duration.millis(500),
                new KeyValue(card1.layoutXProperty(), card4.getLayoutX()),
                new KeyValue(card4.layoutXProperty(), card1.getLayoutX())
                ));
        tl.setAutoReverse(true);
        tl.setCycleCount(Timeline.INDEFINITE);
        tl.play();
    }

    class Card extends HBox{

        private static final String textStyle =
                "-fx-fill: linear-gradient(BROWN, WHITE);"+
                "-fx-font-size: 100px;"+
                "-fx-font-weight: BOLD;"+
                "-fx-stroke-type: outside;"+
                "-fx-stroke-width: 3;"+
                "-fx-stroke: linear-gradient(WHITE, BROWN);"+
                "-fx-blend-mode: hard-light;";

        boolean active;

        public final Text text;

        public Card(int number) {
            setStyle("-fx-effect: dropshadow(one-pass-box, black, 30, 0, 10, 20);");
            text = new Text(""+number);
            text.setStyle(textStyle);
            getChildren().add(text);
        }
    }

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

}

1 个答案:

答案 0 :(得分:12)

  1. 缓存节点(使用您的示例执行此操作会将CPU使用率从核心的100%降至1%)。

    setCache(true);
    setCacheShape(true);
    setCacheHint(CacheHint.SPEED);
    
  2. 阅读javadoc on node caching

  3. 在样式表中定义CSS规则而不是内联样式(如果我记得由于JavaFX中CSS实现的性质而更有效)。

  4. 在open-jfx wiki上查看performance tips and tricks

  5. 阅读相关问题:

  6.   

    我希望计算在GPU中完成。

    JavaFX将在GPU上进行大量计算,但它会做出权衡 - 在CPU上更好地完成一些计算,而JavaFX将使用CPU进行这些类型的计算。您的问题不是在GPU或CPU上进行计算。您的问题是进行了太多计算,因为没有向JavaFX系统提供适当的缓存提示。

      

    使用css来装饰要设置动画的节点是不是一种不好的做法?

    内联css样式通常是不好的做法 - 将css放在样式表中。对于大多数用例,在动画节点上使用CSS是合适的。

      

    确实设置setCache(true)和setCacheHint(CacheHint.SPEED)改进了动画,但它仍然是滞后的。

    动画并没有落后于我的机器,但之后它并没有真正的可比性,因为我的机器中的硬件和软件是从2014年开始,而不是2008年。

    也许尝试更新图形驱动程序并将JavaFX更新为latest development build

    此外,减慢动画速度(例如,给它持续五秒而不是半秒)。当动画移动得非常快时,很难在视觉上检测动画的平滑度。

    JavaFX issue tracker中记录错误报告 - JavaFX开发人员应该能够提供有关如何启用详细JavaFX性能跟踪的其他信息,该跟踪记录JavaFX管道中的呈现步骤并测量其在逐帧(我不知道如何做)。