我一直在努力提高LineChart在JavaFX中的性能,但没有取得很大的成功。我还发现,这似乎是一些程序员在试图显示大数据时发现的一个常见问题(这里的大表示数据> 10,000)。例如,这类数据在科学和工程中非常常见,如果我们能够找到如何加快LineChart in JavaFX的速度,那就太好了。
嗯,我在堆栈溢出中找到了两个类似的问题具有65000个数据点的JavaFX LineChart的性能问题和JavaFX LineChart -绘制数组的帖子。主题具有65000个数据点的JavaFX LineChart的性能问题最后提出了使用Ramer-Douglas-Peucker算法的建议(由Adam提出)!以减少进入LineChart的数据点的数量以加快速度。
然而,在科学和工程数据中,我们通常需要看到图的形状,然后放大以查看图的特定部分的细节。因此,如果我们使用拉姆尔-道格拉斯-派克算法,我们将需要重新绘制的LineChart每次用户放大/缩小,我认为,将花费大量的处理。
因此,我想知道是否有人在如何加快LineChart in JavaFX方面有一些建议。下面是一个示例代码,其中包含了我到目前为止学到的内容。
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);
}
}正如您所看到的,如果您运行这段代码,最大的成本是在呈现方面,而我无法使用这些时间捕获它。然后,在我看来,改进应该集中在那里,但我不知道如何改进。
谢谢。
发布于 2018-03-29 13:15:33
我还使用JavaFX图表进行科学应用,有几十个数据点,并且能够实现实时更新和绘制图形的速度。你需要做两件主要的事情。
首先,我认为Ramer Peucker算法是不必要的复杂.假设您使用的是一个很好的简单的连续函数,那么观察到我们只有有限的显示分辨率就更容易了,而且对于域中的每个像素,我们最多只需要三个或四个数据点来传递尽可能多的信息。例如,第一数据点和最后数据点在像素内各出现一次,在像素内最大和最小数据点分别出现一次。
有一些变化,你可以尝试这个策略,但基本的想法只是一个很好的快速单通下降样本,它应该基本上是无损的。(或者更准确地说,它不应在光栅化的基础上增加额外的代表性损失。)它还将点数限制在可管理的范围内,在我的经验中,它足够快地重新绘制缩放或实时数据更新。但是,如果您为HiDPI显示缩放,或者由于任何原因正在缩放图形组件,则可能会导致问题。
第二部分同样重要:即使您将css设置为不绘制数据点形状,将节点添加到场景仍然要花费相当长的时间。要解决这个问题,只需子类LineChart并覆盖dataItemAdded方法就足够了,在不想绘制形状的情况下,它是不操作的。您还应该在可能的情况下重用已经添加到系列中的数据点,而不是添加新的数据点,比如更喜欢series.getData().get(i).setXValue(...)和series.getData().get(i).setYValue(...)而不是series.setData(...)或series.getData().add(...)。
发布于 2019-06-12 18:04:39
希望这句话不会白费,也不会来得太晚:
一些性能限制是JavaFX实现所固有的:即。许多操作是在JVM中计算的,而不是被推送到底层的基于OpenGL的HW,数据点是在场景图中绘制的过大的Nodes,而不是动态的数据缩减和Canvas的使用.举几个例子。不幸的是,我们发现,如果没有更大的解决方法(例如,final API方法),这些问题(和bug)就无法在原始JavaFX Chart API中得到解决。
因此,我们开发/重新设计了(用于我们的内部应用程序)、开源,并且--希望其他人发现它有用或想做出贡献--在GitHub上发布了我们基于JavaFX的图表库:
https://github.com/GSI-CS-CO/chart-fx
它的主要关注点:性能优化的实时数据可视化在25赫兹的数据集更新率与数万至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
为什么需要一个新的JavaFX库,以及性能比较。其他基于Java和C++/Qt的库也出现在IPAC'19:https://ipac2019.vrws.de/papers/thprb028.pdf上。
注:这是我的第一篇文章,因此没有在线图片。
发布于 2017-10-20 08:20:38
提高多个数据点的图表性能的是删除数据点的“形状”。
例如,通过css:
.chart-line-symbol {
-fx-shape: "";
}或者确保它根本看不见:
.chart-line-symbol {
-fx-background-insets: 0,0;
-fx-background-radius: 0px;
-fx-padding: 0px;
-fx-shape: "";
-fx-background-color: transparent;
}另一种方法是从图表中删除一些数据点。因此,例如,只使用每3.数据点或计算多个数据点的平均值。
https://stackoverflow.com/questions/34771612
复制相似问题