JavaFX(8) - 改善散点图性能

时间:2015-10-02 08:14:51

标签: java performance charts javafx-8

问题:

在下面描述的场景中,我可以通过哪些方式改善渲染时间?

说明

我面临的任务是在JavaFX中的散点图上绘制相当多的点。我从Oracle DB获取数据。

我认为我目前的瓶颈是scatterChart.getData().add(series);

series包含图表中所需的所有数据点。

执行此操作,并在屏幕上呈现图表可能需要几秒到几分钟。在此期间,GUI冻结。

我们正在运行一些带有4核心4线程,Intel HD4000图形的联想智能手机。

完成图表的一些示例如下。后者是目前最糟糕的情况,但随着收集的数据越来越多,将会显示更多的数据。

(由于图像不切实际,只有链接)

Chart with ~5.5K points
Chart with ~75K points

更多信息

我关注了this tutorial因为我是JavaFX的新手,所以我不确定渲染的确切方式。

代码示例

这不是我使用的实际代码,只是为了说明我是如何做事的。

//Reference to the chart in the fxml file.
@FXML
private ScatterChart<Date, Number> scatterChart
= new ScatterChart<>(new DateAxis(), new NumberAxis());

private void handleSelectionUpdate(PerfResultSet newValue){
    //newValue is an object containing all the data from the database
    XYChart.Series<Date, Number> series = new XYChart.Series<>();
    /**
    *   adding all the data from newValue to series as 
    *   XYChart.Data<Date, Number>
    *
    *   this is handled by multiple threads and does not take long
    */

    series.setName("myName");


    //this statement is where the gui freezes
    //can I optimize this in any way?
    scatterChart.getData().add(series);
}

1 个答案:

答案 0 :(得分:3)

我遇到了类似的问题 - 我正在使用Javascript绘制包含许多点到google地图的路线。我取消了考虑当前规模的积分。我看到你的png文件,似乎你真的需要~30-50点来表达以下信息 - 嘿,这个垂直/水平段包含这么多点你可以假设它实线!

下一个问题是最大规模 - 我认为,75K图表中的每条实线实际上都不稳固。我的意思是,在小范围内,我看到很多点像实线____,但在最大尺度上我看到它们为. . . ... . ..但通常,最大比例仅需要小块图表和你可能不是按比例而是按边界消除。再次参考谷歌地图 - 当你缩放地图时,你没有看到整个地球的酷分辨率,但一些小地图。其他边框自动消除。

在这里发布您的代码,有关缩放,缩放的一些信息(您有这样的功能吗?)。如果你没有,并且你的图表总是像链接中的png文件一样,你应该遍历每条垂直或水平线,寻找后续点,并将100个序数点替换为100点的中间点。而不是100实验上找到这样的X,将序列 X点替换为一个中间值点不会影响结果图表。

我重复主要思想 - 存在一些X,这样绘制X 序列点等于在某个固定尺度上绘制1点 - 许多点不能提供精度但只是简单地“覆盖”彼此由于规模和人眼限制。

如果您的比例是常数,则找到X的一些伪代码;

int MAGIC = 50; //change it on each run of your program! You have to find the best value
int counter=1; // points[0] taken as included in accumulating solid segment
int startIndex=0,endIndex;
ArrayList<Integer> compressedDatesArray = new ArrayList<Integer>();
for(int i=1;i<datesArray.length;i++){
  if(deltaBetweenDates(datesArray[i]-datesArray[i-1])==1){
     counter++;
     endIndex=i;
     if(counter==MAGIC){
       counter=0;
       compressedDatesArray.add(datesArray[{endIndex-startIndex)/2]);
       startIndex=endIndex+1;
     }
  }

}

渲染compressedArray,请参阅png。如果结果不好 - chnage MAGIC并重复

<强>更新

你可以二元搜索 MAGIC - 尝试5000,如果在压缩5000点后仍然稳定,如果没有尝试更大的值,请尝试2500等等......人类也可以二元搜索某事= )))

另外,不要忘记记住代表大段的点的Y值。我的意思是,也声明compressedY并添加datesArray[(endIndex-startIndex/2)]

的相应的Y.