RFR: 8197991: Selecting many items in a TableView is very slow
yosbits
github.com+7517141+yososs at openjdk.java.net
Mon Apr 12 08:34:25 UTC 2021
https://bugs.openjdk.java.net/browse/JDK-8197991
The performance of the selectAll and selectRange methods of the MultiSelectionModel class has been greatly improved.
This greatly improves the response when selecting multiple items in ListView and TableView.
However, in TreeView / TreeTableView, the improvement effect is hidden mainly due to the design problem of the cache of TreeUtil.getTreeItem ().
Reference value of the number of data that can be handled within 3 seconds of processing time (before-> after)
ListView
* selectAll: 400_000-> 10_000_000
* selectRange: 7_000-> 70_000
TableView
* selectAll: 8_000-> 700_000
* selectRange: 7_000-> 50_000
You can see performance improvements in the following applications:
``` SelectListViewTest.java
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SelectListViewTest extends Application {
final int ROW_COUNT = 70_000;
// final int ROW_COUNT = 400_000;
// final int ROW_COUNT = 10_000_000;
// final int ROW_COUNT = 7_000;
@Override
public void start(Stage stage) {
ListView<String> listView = new ListView<>();
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
ObservableList<String> items = listView.getItems();
for(int i=0; i<ROW_COUNT; i++) {
String rec = String.valueOf(i);
items.add(rec);
}
BorderPane root = new BorderPane(listView);
Button selectAll = new Button("selectAll");
Button clearSelection = new Button("clearSelection");
Button selectToStart = new Button("selectToStart");
Button selectToEnd = new Button("selectToEnd");
Button selectPrevious = new Button("selectPrevious");
Button selectNext= new Button("selectNext");
selectAll.setFocusTraversable(true);
clearSelection.setFocusTraversable(true);
selectToStart.setFocusTraversable(true);
selectToEnd.setFocusTraversable(true);
selectPrevious.setFocusTraversable(true);
selectNext.setFocusTraversable(true);
root.setRight(new VBox(6, selectAll, selectToStart, selectToEnd, selectPrevious, selectNext, clearSelection));
stage.setScene(new Scene(root, 600, 600));
selectAll.setOnAction((e)->selectAll(listView));
clearSelection.setOnAction((e)->clearSelection(listView));
selectToStart.setOnAction((e)->selectToStart(listView));
selectToEnd.setOnAction((e)->selectToLast(listView));
selectPrevious.setOnAction((e)->selectPrevious(listView));
selectNext.setOnAction((e)->selectNext(listView));
stage.show();
}
private void selectAll(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().selectAll();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void clearSelection(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().clearSelection();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectToStart(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().selectRange(0, listView.getSelectionModel().getSelectedIndex());
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectToLast(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().selectRange(listView.getSelectionModel().getSelectedIndex(), listView.getItems().size());
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectPrevious(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().selectPrevious();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectNext(ListView listView) {
long t = System.currentTimeMillis();
listView.getSelectionModel().selectNext();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
public static void main(String[] args) {
Application.launch(args);
}
}
``` SelectTableViewTest.java
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SelectTableViewTest extends Application {
final int ROW_COUNT = 700_000;
// final int ROW_COUNT = 80_000;
// final int ROW_COUNT = 50_000;
// final int ROW_COUNT = 8_000;
final int COL_COUNT = 3;
@Override
public void start(Stage stage) {
TableView<String[]> tableView = new TableView<>();
tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
final ObservableList<TableColumn<String[], ?>> columns = tableView.getColumns();
for(int i=0; i<COL_COUNT; i++) {
TableColumn<String[], String> column = new TableColumn<>("Col"+i);
final int colIndex=i;
column.setCellValueFactory((cell)->new SimpleStringProperty(cell.getValue()[colIndex]));
column.setPrefWidth(150);
columns.add(column);
}
ObservableList<String[]> items = tableView.getItems();
for(int i=0; i<ROW_COUNT; i++) {
String[] rec = new String[COL_COUNT];
for(int j=0; j<rec.length; j++) {
rec[j] = i+":"+j;
}
items.add(rec);
}
BorderPane root = new BorderPane(tableView);
Button selectAll = new Button("selectAll");
Button clearSelection = new Button("clearSelection");
Button selectToStart = new Button("selectToStart");
Button selectToEnd = new Button("selectToEnd");
Button selectPrevious = new Button("selectPrevious");
Button selectNext= new Button("selectNext");
selectAll.setFocusTraversable(true);
clearSelection.setFocusTraversable(true);
selectToStart.setFocusTraversable(true);
selectToEnd.setFocusTraversable(true);
selectPrevious.setFocusTraversable(true);
selectNext.setFocusTraversable(true);
root.setRight(new VBox(6, selectAll, selectToStart, selectToEnd, selectPrevious, selectNext, clearSelection));
stage.setScene(new Scene(root, 600, 600));
selectAll.setOnAction((e)->selectAll(tableView));
clearSelection.setOnAction((e)->clearSelection(tableView));
selectToStart.setOnAction((e)->selectToStart(tableView));
selectToEnd.setOnAction((e)->selectToLast(tableView));
selectPrevious.setOnAction((e)->selectPrevious(tableView));
selectNext.setOnAction((e)->selectNext(tableView));
stage.show();
}
private void selectAll(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().selectAll();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void clearSelection(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().clearSelection();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectToStart(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().selectRange(0, tableView.getSelectionModel().getFocusedIndex());
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectToLast(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().selectRange(tableView.getSelectionModel().getFocusedIndex(), tableView.getItems().size());
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectPrevious(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().selectPrevious();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
private void selectNext(TableView tableView) {
long t = System.currentTimeMillis();
tableView.getSelectionModel().selectNext();
System.out.println("time:"+ (System.currentTimeMillis() - t));
}
public static void main(String[] args) {
Application.launch(args);
}
}
-------------
Commit messages:
- 8197991: Fix multi-select performance issues
- 8197991: Fix multi-select performance issues
Changes: https://git.openjdk.java.net/jfx/pull/127/files
Webrev: https://webrevs.openjdk.java.net/?repo=jfx&pr=127&range=00
Issue: https://bugs.openjdk.java.net/browse/JDK-8197991
Stats: 58 lines in 2 files changed: 50 ins; 0 del; 8 mod
Patch: https://git.openjdk.java.net/jfx/pull/127.diff
Fetch: git fetch https://git.openjdk.java.net/jfx pull/127/head:pull/127
PR: https://git.openjdk.java.net/jfx/pull/127
More information about the openjfx-dev
mailing list