Java 折线图性能随时间而降低

Java 折线图性能随时间而降低,java,multithreading,performance,javafx-2,javafx-8,Java,Multithreading,Performance,Javafx 2,Javafx 8,因此,我们正在开发一个信号处理应用程序,PC中有一种特定类型的硬件和一个与之通信的C驱动程序。 应用程序前端/gui是用JavaFX编写的。我们在JavaFX线形图上遇到了一些问题,我们正在测量电信号频率,并试图将其绘制在前面提到的线形图上 在采集到1000个样本之前,测量一直在循环中运行,我们使用100Hz信号进行测试,这意味着需要10秒才能获得这1000个样本 有一个单独的“折线图”线程运行并检查(每10毫秒)是否有新样本可用,如果有,这些样本将添加到折线图中,如果测量线程完成,折线图线程将

因此,我们正在开发一个信号处理应用程序,PC中有一种特定类型的硬件和一个与之通信的C驱动程序。 应用程序前端/gui是用JavaFX编写的。我们在JavaFX线形图上遇到了一些问题,我们正在测量电信号频率,并试图将其绘制在前面提到的线形图上

在采集到1000个样本之前,测量一直在循环中运行,我们使用100Hz信号进行测试,这意味着需要10秒才能获得这1000个样本

有一个单独的“折线图”线程运行并检查(每10毫秒)是否有新样本可用,如果有,这些样本将添加到折线图中,如果测量线程完成,折线图线程将重置折线图(清除系列数据),然后重新开始该过程

在最初的20分钟内,一切都正常运行,之后,线形图似乎“减速”,看起来绘图速度/动态性不如开始时

我们在应用程序中检查了几乎所有可能的内容,但没有发现任何内容,因此我们创建了一个单独的项目,该项目只有折线图和一个线程,该线程每10毫秒向图表添加一次样本(最多1000个样本)。我们观察到了同样的行为,下面是它的表现:

        Thread t = new Thread(new Runnable() {
        @Override
        public void run() {

            int iteration = 0;
            long start = 0;
            long stop = 0;

            while (run) {

                CountDownLatch latch = new CountDownLatch(1);
                start = System.currentTimeMillis();

                for (int i = 0; i < 1001; i++) {
                    double ran = random(50, 105);
                    final int c = i;

                    Platform.runLater(() -> {
                        series.getData().add(new XYChart.Data<>(c, ran));

                        if (c == 1000) {
                            System.out.print("Points:  " + series.getData().size());
                            series.getData().clear();

                            latch.countDown();
                        }
                    });

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                iteration++;
                stop = System.currentTimeMillis();

                try {
                    latch.await();
                } catch (InterruptedException e) {}

                System.out.println(", Iteration : " + iteration + ", elapsed: " + (stop - start) + " [ms]");
            }
        }
    });
Thread t=新线程(new Runnable(){
@凌驾
公开募捐{
int迭代=0;
长启动=0;
长停止=0;
while(运行){
CountDownLatch闩锁=新的CountDownLatch(1);
start=System.currentTimeMillis();
对于(int i=0;i<1001;i++){
双随机数=随机数(50105);
最终int c=i;
Platform.runLater(()->{
series.getData().add(新的XYChart.Data(c,ran));
如果(c==1000){
System.out.print(“Points:+series.getData().size());
series.getData().clear();
倒计时();
}
});
试一试{
睡眠(10);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
迭代++;
停止=System.currentTimeMillis();
试一试{
satch.wait();
}捕获(中断异常e){}
System.out.println(“,迭代:“+Iteration+”,经过:“+(停止-启动)+”“[ms]”);
}
}
});
我们错过了什么?在上述示例中,为什么性能在约30-45分钟后下降?有什么想法吗


上面的代码运行了8小时,每次将所有点添加到图表中,“绘制时间”都是可比较的(在10100ms和10350ms之间)。

我看到的代码没有任何错误,但是,您继续添加到序列中。我不认为这是代码的问题,但这是机器试图保持和管理所有的点,你说10秒1000,这意味着20分钟后,你有120000点在存储中,正在管理和绘制。假设你记录到十分之一的位置,那是一吨的存储空间,而且很可能,你会看到所有这些信息的处理速度都变慢了。简单地说,机器无法处理它。

这是一个较老的问题,但如果有人无意中发现它,寻找性能问题,那么数据添加到系列中的方式将受到巨大冲击。 在可能的情况下,应将点一次全部添加到序列中,而不是单独添加


在上述示例中,如果代码将所有遇到的数据点收集到一个列表中,然后使用addAll调用将其添加到整个列表中,则性能会提高。addAll调用的频率可以根据审美性能的反复试验来设置,但是用户可以看到的赫兹远低于平台上的赫兹。RunLater正在尝试更新。

我找到了原因,在安装了AMD GFX卡的Linux平台上缺乏硬件加速。Oracle并没有提供硬件支持,所以JavaFX正在退回到一些糟糕的支持,导致性能下降。原始帖子中的代码在Win机器或带有Nvidia卡的Linux机器上没有问题,但在带有AMD卡的Linux上没有问题。在使用amd卡的Linux上,您必须手动执行软件加速(与默认加速相反)。

感谢您的输入,不幸的是,事实并非如此。每次将第1000个样本添加到图表中时,图表系列都会被清除,如您在if块中所看到的。在这种情况下,我不太确定,可能它分配了120000点的存储空间,一次100点。有时java会变得有点粘。我不知道是什么原因,也不知道为什么会这样,但它偶尔会发生;重新监控内存消耗,一切看起来都很好,CPUhmm也一样,这一定是java变得黏糊糊的例子之一,我不知道是什么原因,但java的清理过程有点混乱,你可能会说我们观察到了相同的行为,每次都将所有点添加到图表中,“绘图时间”具有可比性。难道不应该有一个减速,所以时间都不一样吗?此外,这只是一个想法,在股市图表中,我可以删除数据,而且它永远不会慢下来。如果(c>1000)series.getData().remove(0500),则可能
;这就是我想的,这就是为什么我开始测量这一次,令我惊讶的是,每次迭代都处于可比的水平。你在循环运行你的图表吗?请问有哪些参数?有多少个点,刷新率是多少,你运行了多长时间?我从一个插座中获取数据,最大3hz,1000个点,直到我删除旧的点。我不把它当作一种工具