I've been trying to improve the performance of LineChart in JavaFX but without great success. I also have found that this seems to be a common problem that some programmers have found when trying to display big data (big here stands for datasize > 10,000). For instance, this kind of data is pretty common in the science and engineering and it would be great if we could figure out how to speed up the LineChart in JavaFX.
Well, I found two posts here in the stackoverflow with a similar question Performance issue with JavaFX LineChart with 65000 data points and JavaFX LineChart - draw array. The topic Performance issue with JavaFX LineChart with 65000 data points ends up with a suggestion (by Adam) to use the Ramer–Douglas–Peucker algorithm! to reduce the number of data points into the LineChart in order to speed up.
However, in scientific and engineering data, we usually need to see the plot shape and then zoom in to see the details in specific parts of the plot. Hence, if we use Ramer-Douglas-Peucker algorithm, we would be required to redraw the LineChart every time the user zoom in/out that, I think, would cost a lot of processing.
Therefore, I would like to know if someone have some tips in how to speed up the LineChart in JavaFX. Here is an example code containing what I've learned so far.
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);
}
}
As you can see if you run this code, the greatest cost is in rendering, which I could not capture using those timings. Then, in my view, the improvement should be focused there but I do not know how.
Thank you.