JavaFx 动画性能不佳,消耗了我所有的 CPU [英] JavaFx animation poor performance, consumes all my CPU

查看:40
本文介绍了JavaFx 动画性能不佳,消耗了我所有的 CPU的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了以下演示程序.四个 HBox(s) 每个包含一个 Text 节点,被添加到根(组).第一个和最后一个动画带有时间轴来交换它们的位置.所有 HBox(s) 都具有相同的 css 样式.

结果是非常低的每秒帧数"动画.我有一个双核 E7400 2.8Ghz Cpu.100%使用了一个核心.我希望计算在 GPU 中完成.移除大部分 css(尤其是阴影效果)后,动画变得更流畅了.我可以做些什么来保持视觉效果,同时我有更好的表现?使用 css 来装饰要动画的节点是否被认为是一种不好的做法?

我还使用了 -Dprism.verbose=true 来检查硬件加速是否开启.看起来一切正常

Prism 管道初始化命令:d3d sw使用平台文本光栅化器使用基于本机的双鱼座光栅化器使用脏区优化不为图元使用纹理遮罩不强制纹理的 2 个尺寸的幂使用硬件 CLAMP_TO_ZERO 模式选择 HiDPI 像素缩放棱镜管道名称 = com.sun.prism.d3d.D3DPipeline正在加载 D3D 本机库...成功了.D3DPipelineManager:创建 D3D9 设备Direct3D 初始化成功(X) Got class = class com.sun.prism.d3d.D3DPipeline初始化棱镜管道:com.sun.prism.d3d.D3DPipeline支持的最大纹理大小:8192最大纹理大小限制为 4096操作系统信息:Windows 7 内部版本 7601D3D 驱动程序信息:ATI Radeon HD 4800 系列\\.\DISPLAY1驱动程序 aticfx32.dll,版本 8.17.10.1129像素着色器 3.0 版设备:ven_1002、dev_9440、subsys_0502174B支持的最大多重采样数:4垂直同步:真实 vpipe:真实正在加载 Prism 通用本机库...成功了.

这是程序

public class Sample extends Application{public void start(Stage primaryStage) 抛出异常 {组根 = new Group();卡 card1 = 新卡(1);卡 card2 = 新卡 (2);卡 card3 = 新卡 (3);卡 card4 = 新卡(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();时间线 tl = 新时间线(新关键帧(Duration.millis(500),新 KeyValue(card1.layoutXProperty(), card4.getLayoutX()),新键值(card4.layoutXProperty(),card1.getLayoutX())));tl.setAutoReverse(true);tl.setCycleCount(Timeline.INDEFINITE);tl.play();}class Card 扩展了 HBox{私有静态最终字符串 textStyle =-fx-fill:线性渐变(棕色,白色);"+"-fx-font-size: 100px;"+"-fx-font-weight: 粗体;"+"-fx-stroke-type: 外面;"+"-fx-stroke-width: 3;"+-fx-stroke:线性渐变(白色,棕色);"+-fx-混合模式:强光;";布尔活动;公开最终文本文本;公共卡(整数){setStyle("-fx-effect: dropshadow(one-pass-box, black, 30, 0, 10, 20);");text = new Text(""+number);text.setStyle(textStyle);getChildren().add(text);}}公共静态无效主(字符串 [] args){发射(参数);}}

解决方案

  1. 缓存节点(对您的样本执行此操作将 CPU 使用率从一个核心的 100% 降低到 1%).

    setCache(true);setCacheShape(true);setCacheHint(CacheHint.SPEED);

  2. 阅读javadoc关于节点缓存.

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

  4. 查看性能提示和技巧 在 open-jfx wiki 上.

  5. 阅读相关问题:

<块引用>

我希望在 GPU 中完成计算.

JavaFX 将在 GPU 上进行大量计算,但它会进行权衡 - 有些计算最好在 CPU 上完成,而 JavaFX 将使用 CPU 进行此类计算.您的问题不在于在 GPU 或 CPU 上进行计算.您的问题是进行了太多计算,因为尚未向 JavaFX 系统提供适当的缓存提示.

<块引用>

使用 css 来装饰要动画的节点是否被认为是一种不好的做法?

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

<块引用>

确实设置 setCache(true) 和 setCacheHint(CacheHint.SPEED) 改善了动画,但仍然滞后.

动画在我的机器上没有滞后,但实际上没有可比性,因为我机器中的硬件和软件是 2014 年的,而不是 2008 年的.

也许尝试更新您的图形驱动程序并将 JavaFX 更新到最新开发版本.

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

JavaFX 问题跟踪器中记录错误报告 - JavaFX 开发人员应该能够提供额外的有关如何打开详细 JavaFX 性能跟踪的信息,该跟踪记录 JavaFX 管道中的渲染步骤并逐帧测量其性能(我不知道如何执行此操作).

I have written the following demonstration program. Four HBox(s) containing one Text node each, are added to the root (Group). The first and last are animated with a timeline to swap their positions. All the HBox(s) have the same css style.

The result is a very low 'frames per second' amimation. I have an dual core E7400 2.8Ghz Cpu. The one core was used 100%. I expected the computations to be done in GPU instead. After removing most of the css (especially the shadow effect) the animation went smoother. Is there something I can do in order to preserve the visual effects while I have a better performance? Is it considered a bad practice to use css to decorate nodes that are going to be animated?

I also used the -Dprism.verbose=true to check if the hardware accelaration is on. Everything seems ok

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.

and here is the program

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. Cache the node (doing this with your sample dropped the CPU usage from 100% of a core to 1%).

    setCache(true);
    setCacheShape(true);
    setCacheHint(CacheHint.SPEED);
    

  2. Read the javadoc on node caching.

  3. Define your CSS rules in a stylesheet and not inline styles (if I recall that is more efficient due to the nature of the CSS implementation in JavaFX).

  4. Take a look at performance tips and tricks on the open-jfx wiki.

  5. Read related questions:

I expected the computations to be done in GPU instead.

JavaFX will do lots of computations on the GPU, however it does a tradeoff - some computations are better done on a CPU and JavaFX will use the CPU for these kinds of computations. Your issue is not one of having computations done on the GPU or CPU. Your issue is having too many computations done because appropriate caching hints have not been provided to the JavaFX system.

Is it considered a bad practice to use css to decorate nodes that are going to be animated?

Inline css styles are bad practice in general - put the css in a stylesheet. Using CSS on animated nodes is fine for most use cases.

Indeed setting setCache(true) and setCacheHint(CacheHint.SPEED) improved the animation but it is still laggy.

The animation does not lag on my machine, but then it is not really comparable because the hardware and software in my machine is from 2014, not 2008.

Perhaps try updating your graphics drivers and updating JavaFX to the latest development build.

Also, slow down the animation (e.g. give it a duration of five seconds rather than half a second). It can be hard to visually detect the smoothness of an animation when it moves very quickly.

Log a bug report in the JavaFX issue tracker - the JavaFX developers should be able to supply additional information on how to do turn on detailed JavaFX performance tracking which logs the rendering steps in the JavaFX pipeline and measures their performance on a frame by frame basis (I don't know how to do this).

这篇关于JavaFx 动画性能不佳,消耗了我所有的 CPU的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆