RFR: 8197991: Selecting many items in a TableView is very slow
Kevin Rushforth
kcr at openjdk.java.net
Tue Apr 21 12:53:06 UTC 2020
On Thu, 2 Apr 2020 17:37:26 GMT, Dalibor Topic <robilad at openjdk.org> wrote:
>> 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);
>> }
>> }
>
> Hi,
> I couldn't find you listed at https://www.oracle.com/technetwork/community/oca-486395.html . Please send me an e-mail
> at dalibor.topic at oracle.com with information about your OCA, so that I can look it up.
@aghaisas can you also review this?
-------------
PR: https://git.openjdk.java.net/jfx/pull/127
More information about the openjfx-dev
mailing list