JavaFX滚动表更新性能会随着时间的推移而降低 [英] JavaFX scrolling table update performance degrades over time

查看:139
本文介绍了JavaFX滚动表更新性能会随着时间的推移而降低的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示最后N个项目的TableView,顶部的新项目,从底部删除项目等等......似乎正在发生的事情是CPU负载随着时间的推移而增加,以至于同一台计算机上的其他X应用程序变得迟缓。



平台详细信息:Redhat 6.7,32位,Java 1.8u40



我试过的东西




  • 引入runLater() - 原始代码从非FX线程更新了可观察列表 - 显然这是错误的

  • Optimize - 如果尚未进行更新,则仅在JavaFX应用程序线程上放置新的Runnables

  • 优化-bunk更新Observable列表而不是单独添加

  • 使用jvisual VM来识别任何内存泄漏,找不到任何内容。

  • 我试图重新创建这个


    • Windows 7(在金属上) - JDK 8u40 64位=>未发生

    • Ubuntu 16.04 JDK 8u40 64位(在具有vmwgfx的VM内)=>不会发生

    • Ubuntu 16.04 OpenJDK + OpenJFX最新版(8u91)(金属上)=> 发生




JVisual VM - 新硬件上的Redhat 6u7(32位)





此问题属于较大的应用程序的一部分,但我已将其作为下面的小例子进行了隔离。这使得其他应用程序在几分钟后变得缓慢,但仅限于Redhat 6u7平台。

 公共类TableUpdater扩展应用程序{
private int maxItems = 30;
private AtomicBoolean pending = new AtomicBoolean();
public class Thing {
private String foo;
public Thing(String foo){
this.foo = foo;
}
public String getFoo(){
return foo;
}
@Override
public int hashCode(){
return foo.hashCode();
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof Thing)){
return false;
}
return((Thing)obj).foo.equals(foo);
}
}

public static void main(String [] args){
launch(args);
}

private int counter = 0;
private ObservableList< Thing>数据;
private List< Thing> itemsToAdd = Collections.synchronizedList(new ArrayList< Thing>());

@Override
public void start(Stage primaryStage)抛出异常{
TableView< Thing> table = new TableView<>();
data = FXCollections.observableArrayList();
table.setItems(data);

TableColumn< Thing,String> fooCol = new TableColumn<>(Foo);
fooCol.setCellValueFactory(new PropertyValueFactory< Thing,String>(foo));
table.getColumns()。addAll(fooCol);

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() - > {
add(new Thing(String.format(%08d,counter ++)));
},0,2,TimeUnit.MILLISECONDS);

primaryStage.setScene(new Scene(table));
primaryStage.setWidth(400);
primaryStage.setHeight(400);
primaryStage.show();
}

private void add(事物){
itemsToAdd.add(thing);

if(!pending.getAndSet(true)){
Platform.runLater(() - > {
synchronized(itemsToAdd){
Collections.reverse( itemsToAdd);
data.addAll(0,itemsToAdd);
itemsToAdd.clear();
}
if(data.size()> maxItems){
data.remove(maxItems,data.size());
}
pending.set(false);
});
}
}
}

问题




  • 这个问题与我更新表格或底层错误的方式有关吗?

  • 更高效更新表格的方法?


解决方案

尝试使用G1GC垃圾收集器。我有一个类似但不完全相同的问题(tableview中的大量持久对象),这是通过使用G1GC解决的。



java XX: + UseG1GC


I have a TableView that shows last N items, new items at top, remove items from the bottom etc... What appears to be happening is CPU load increases over time to point where other X applications on same machine become sluggish.

Platform details: Redhat 6.7, 32 bit, Java 1.8u40

Things I've tried

  • Introduced runLater() - original code updated the observable list from a non-FX thread - apparently this is wrong
  • Optimize - only place new Runnables on JavaFX application thread if there isn't already an update in progress
  • Optimize -bulk updates to the Observable list rather than individual adds
  • used jvisual VM to indentify any memory leaks, couldn't find anything.
  • I've tried to recreate this
    • Windows 7 (on metal) - JDK 8u40 64 bit => does not occur
    • Ubuntu 16.04 JDK 8u40 64 bit (inside a VM with vmwgfx) => does not occur
    • Ubuntu 16.04 OpenJDK + OpenJFX latest (8u91) (on metal) => does occur

JVisual VM - Redhat 6u7 (32bit) on newish hardware

JVisual VM - Ubuntu 16.04 (64bit) on old hardware (2008 iMac)

This issue was part of larger app, but I've isolated it as a smaller example below. This makes other apps sluggish after a couple of minutes, but only on the Redhat 6u7 platform.

public class TableUpdater extends Application {
    private int maxItems = 30;
    private AtomicBoolean pending = new AtomicBoolean();
    public class Thing {
        private String foo;
        public Thing(String foo) {
            this.foo = foo;
        }
        public String getFoo() {
            return foo;
        }
        @Override
        public int hashCode() {
            return foo.hashCode();
        }
        @Override
        public boolean equals(Object obj) {
            if (! (obj instanceof Thing)) {
                return false;
            }
            return ((Thing)obj).foo.equals(foo);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    private int counter = 0;
    private ObservableList<Thing> data;
    private List<Thing> itemsToAdd = Collections.synchronizedList(new ArrayList<Thing>());

    @Override
    public void start(Stage primaryStage) throws Exception {
        TableView<Thing> table = new TableView<>();
        data = FXCollections.observableArrayList();
        table.setItems(data);

        TableColumn<Thing, String> fooCol = new TableColumn<>("Foo");
        fooCol.setCellValueFactory(new PropertyValueFactory<Thing, String>("foo"));
        table.getColumns().addAll(fooCol);

        Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
            add(new Thing(String.format("%08d", counter++)));
        }, 0, 2, TimeUnit.MILLISECONDS);

        primaryStage.setScene(new Scene(table));
        primaryStage.setWidth(400);
        primaryStage.setHeight(400);
        primaryStage.show();
    }

    private void add(Thing thing) {
        itemsToAdd.add(thing);

        if (!pending.getAndSet(true)) {
            Platform.runLater(() -> {
                synchronized (itemsToAdd) {
                    Collections.reverse(itemsToAdd);
                    data.addAll(0, itemsToAdd);
                    itemsToAdd.clear();
                }
                if (data.size() > maxItems) {
                    data.remove(maxItems, data.size());
                }
                pending.set(false);
            });
        }
    }
}

Questions

  • Is this issue something to do with way I'm updating the table or an underlying bug?
  • Any more efficient ways to update the table?

解决方案

Try using the G1GC garbage collector. I had a similar, but not identical, issue (large number of persistent objects in tableview) that was resolved by using G1GC.

java XX:+UseG1GC

这篇关于JavaFX滚动表更新性能会随着时间的推移而降低的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆