JavaFX LineChart性能

Hug*_*lan 12 java performance javafx javafx-8

我一直在努力提高JavaFX中LineChart的性能,但没有取得很大的成功.我也发现这似乎是一些程序员在尝试显示大数据时发现的常见问题(这里的大数据代表数据大于10,000).例如,这种数据在科学和工程中非常普遍,如果我们能够弄清楚如何在JavaFX中加速LineChart,那将会很棒.

好吧,我在stackoverflow中发现了两个帖子,类似的问题JavaFX LineChart的性能问题有65000个数据点JavaFX LineChart - 绘制数组.主题性能问题的JavaFX线型图有65000个数据点结束了(亚当)建议使用道格拉斯-普克算法!减少进入LineChart的数据点数量以加快速度.

但是,在科学和工程数据中,我们通常需要查看绘图形状,然后放大以查看绘图特定部分的详细信息.因此,如果我们使用Ramer-Douglas-Peucker算法,我们将需要在每次用户放大/缩小时重绘LineChart,我认为这将花费大量处理.

因此,我想知道是否有人在如何加速JavaFX中的LineChart方面有一些提示.这是一个示例代码,包含我到目前为止学到的内容.

    import java.util.ArrayList;
    import java.util.List;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.chart.LineChart;
    import javafx.scene.chart.NumberAxis;
    import javafx.scene.chart.XYChart;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;

    public class TestingLineChart extends Application {

@Override
public void start(Stage primaryStage) {
    long startTime, endTime;
    startTime = System.nanoTime();

    StackPane root = new StackPane();

    NumberAxis xAxis = new NumberAxis();
    NumberAxis yAxis = new NumberAxis();

    LineChart<Number, Number> lineChartPlot = new LineChart<>(xAxis, yAxis);
    // set them false to make the plot faster
    lineChartPlot.setAnimated(false);
    lineChartPlot.setCreateSymbols(false);

    List<XYChart.Data<Double, Double>> data = new ArrayList<>();

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



    endTime = System.nanoTime();
    System.out.println("Time (ms) for creation: " + (endTime - startTime)/1e6);


    startTime = System.nanoTime();
    for (int n = 0; n < 1e5; n++) {
        data.add(new XYChart.Data(n, Math.random()));
    }
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    XYChart.Series dataSeries = new XYChart.Series<>();

    dataSeries.setName("data"); // taking the data
    dataSeries.getData().addAll(data); // taking the data

    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data to series: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    lineChartPlot.getData().add(dataSeries);
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding data to LineChart: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    root.getChildren().add(lineChartPlot);
    endTime = System.nanoTime();
    System.out.println("Time (ms) for adding LineChart StackPane: " + (endTime - startTime)/1e6);

    startTime = System.nanoTime();
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
    endTime = System.nanoTime();
    System.out.println("Time (ms) for showing: " + (endTime - startTime)/1e6);
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果您运行此代码,最大的成本是渲染,我无法使用这些时间捕获.那么,在我看来,改进应该集中在那里,但我不知道如何.

谢谢.

Eli*_*nko 12

我还将JavaFX图表用于具有数十个数据点的科学应用程序,并且能够实现更新和绘制图形的实时速度.您需要做两件事.

首先,我认为Ramer-Douglas-Peucker算法是不必要的复杂.假设您正在使用一个简单的连续函数,则更容易观察到我们只有有限的显示分辨率,并且对于域中的每个像素,我们不需要多于三个或四个数据点来传达尽可能多的信息尽可能.例如,第一个和最后一个数据点各一个出现在一个像素内,一个数据点用于像素内的最大值和最小值.

您可以尝试这种策略的一些变化,但基本的想法只是一个很好的快速单通道下采样,它应该基本上是无损的.(或者更确切地说,它应该在光栅化之外不会增加任何额外的代表性损失.)它还将点数限制为可管理的东西,并且根据我的经验,它足以快速重绘缩放或实时数据更新.但是,如果您有HiDPI的显示缩放或者出于任何原因缩放图形组件,它可能会导致问题.

第二部分同样重要:即使您将css设置为不绘制数据点形状,仍然需要花费不可思议的长时间将节点添加到场景中.为了解决这个问题,在不希望绘制形状的情况下,LineChart将该dataItemAdded方法子类化并重写为无操作似乎已足够.您还应该尽可能重新使用已添加到系列中的数据点,而不是添加新数据点,即prefer series.getData().get(i).setXValue(...)series.getData().get(i).setYValue(...)to series.setData(...)series.getData().add(...).


Ang*_*ond 7

希望这个评论没有白费或来得太晚:

一些性能限制是 JavaFX 实现固有的:即。许多操作是在 JVM 内计算的,而不是被推送到基于 OpenGL 的底层硬件,数据点Nodes在场景图中绘制过大,而不是动态数据减少和使用Canvas......等等。不幸的是,我们发现如果没有final围绕原始 JavaFX ChartAPI 的更大的变通方法(例如API 方法),就无法解决其中的许多问题(和错误)。

因此,我们开发/重新设计(针对我们的内部应用程序)、开源,并且——希望其他人发现它有用或想要做出贡献——在 GitHub 上发布了我们基于 JavaFX 的图表库:

https://github.com/GSI-CS-CO/chart-fx

其主要关注点:在 25 Hz 更新率下对具有数字信号处理应用中常见的 1 万到 500 万个数据点的数据集进行性能优化的实时数据可视化。性能图、示例和文档可在 GitHub 上获得:

https://github.com/GSI-CS-CO/chart-fx/raw/master/docs/pics/chartfx-example1.png https://github.com/GSI-CS-CO/chart-fx/raw /master/docs/pics/chartfx-performance1a.png https://github.com/GSI-CS-CO/chart-fx/raw/master/docs/pics/chartfx-performance1.png

在 IPAC'19 上介绍了为什么需要新的 JavaFX 库以及与其他基于 Java 和 C++/Qt 的库的性能比较的动机:https ://ipac2019.vrws.de/papers/thprb028.pdf

注意这是我的第一篇文章,因此没有内嵌图片