JavaFX滚动表更新性能会随着时间的推移而降低

问题描述 投票:12回答:1

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

平台细节:Redhat 6.7,32位,Java 1.8u40

我尝试过的事情

  • 引入了runLater() - 原始代码从非FX线程更新了可观察列表 - 显然这是错误的
  • 优化 - 如果尚未进行更新,则仅在JavaFX应用程序线程上放置新的Runnables
  • 优化-bulk更新Observable列表而不是单独添加
  • 使用visualVM识别任何内存泄漏,找不到任何东西。
  • 我试图重新创造这个 Windows 7(在金属上) - JDK 8u40 64位=>不会发生 Ubuntu 16.04 JDK 8u40 64位(在带有vmwgfx的VM内)=>不会发生 Ubuntu 16.04 OpenJDK + OpenJFX最新版(8u91)(金属上)=>确实发生

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

Redhat 6u7

VisualVM - 旧硬件上的Ubuntu 16.04(64位)(2008 iMac)

Ubuntu 16.04 on Intel iMac

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

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);
            });
        }
    }
}

问题

  • 这个问题与我更新表或底层错误的方式有关吗?
  • 更新表的更有效方法?
java multithreading performance javafx javafx-8
1个回答
0
投票

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

java XX:+UseG1GC

© www.soinside.com 2019 - 2024. All rights reserved.