Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8170304

Column re-ordering slow for large column tableviews after tablemenu popup is shown

XMLWordPrintable

    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      Java 8 Update 112 (Also an issue on Java 8 update 102)

      ADDITIONAL OS VERSION INFORMATION :
      Window 7 (64 bit ) and Windows 10 (64bit)

      A DESCRIPTION OF THE PROBLEM :
      I have a TableView with large number of colums (e.g. more than 40).
      Column re-ordering works with well initially. However after you display the menu for the tableview and return back to the tableview. Re-odering the columns becomes very slow.

      The issue seems to be popup menu, it seems to be registering an additonal column listener when it's intantiated, it seem this is causing the slowness when re-ordering.



      REGRESSION. Last worked in version 7u76

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Attached is an example to re-produce the issue.

      To confirm what the speed of column re-odering should be like.
      (1) Re-ordering the columns - You will see the performance is satisfactory.
      (2) Now click on the + button to show the menu of the tableview. You don't actually need to select anything ( just getting the popup menu to come up is enough)
      (3) Now re-odering the columns. You will see column re-ordering is now much slower.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      After showing the table menu, the perfomance of column re-ordering should be unaffected.
      ACTUAL -
      Displaying the popup menu causes column re-ordering to be slow.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.LinkedHashMap;
      import javafx.application.Application;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      import javafx.beans.value.ObservableValue;
      import javafx.collections.FXCollections;
      import javafx.collections.ObservableList;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.TableView;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.scene.layout.BorderPane;
      import javafx.stage.Stage;
      import javafx.util.Callback;

      public class LargeColumnTableView extends Application {

          @Override
          public void start(Stage primaryStage) {

              ArrayList<Student> students=new ArrayList<>();
              for (int i=0; i<10000; i++) {
                  students.add(new Student("student "+i));
              }

              TableView<Student> studentTable = new TableView<>(FXCollections.observableArrayList(students));
              studentTable.setTableMenuButtonVisible(true);
              TableColumn<Student, String> firstNameColumn = new TableColumn<>("name");
              firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
              studentTable.getColumns().add(firstNameColumn);

              int maxAss = 0;
              for (Student student : students) {
                  maxAss = Math.max(maxAss, student.map.size());
              }

              Callback<TableColumn.CellDataFeatures<Student, String>, ObservableValue<String>> callBack =
                      param -> param.getValue().map.containsKey(
                              "exam"+Integer.toString((int)param.getTableColumn().getUserData()))
                              ? new SimpleStringProperty(String.format("%.1f",100d*param.getValue().map.get(
                              "exam"+Integer.toString((int)param.getTableColumn().getUserData()))))
                              :new SimpleStringProperty("");

              ObservableList<TableColumn<Student, String>> assCols = FXCollections.observableArrayList();
              for (int i = 1; i<=maxAss; i++){
                  TableColumn<Student,String> tmpCol = new TableColumn<>("Exam Result "+Integer.toString(i));
                  tmpCol.setUserData(i);
                  tmpCol.setCellValueFactory(callBack);
                  assCols.add(tmpCol);
              }
              studentTable.getColumns().addAll(assCols);

              BorderPane borderPane=new BorderPane(studentTable);
              borderPane.setTop(new Label("Performance Issue\nRe-ordering columns is fast.\nBUT after popup menu table menu is launched, re-ordering becomes very slow "));

              primaryStage.setTitle("Table with large number of columns");
              Scene scene = new Scene(borderPane, 600, 400);
              primaryStage.setScene(scene);
              primaryStage.show();
          }

          public class Student {

              private final StringProperty firstName = new SimpleStringProperty();
              public StringProperty firstNameProperty(){return firstName;}
              public final HashMap<String, Double> map;

              public Student(String fn) {
                  firstName.set(fn);
                  map = new LinkedHashMap<>();
                  for (int i = 0; i <= 100; i++) {
                      double grade = Math.random();
                      //if (grade > .5) {
                          map.put("exam" + Integer.toString(i), grade);
                    // }
                  }
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Not show the tablemenu button - however this will result in loss of functionality as users will not be able to hide/unhide columns without incurring performance penalty.


            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: