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

TreeView will take an exponential time for the number of additional items in the root grandchild item.

    Details

    • Type: Bug
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 8, 9, 10, openjfx11
    • Fix Version/s: tbd
    • Component/s: javafx
    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      generic

      Description

      FULL PRODUCT VERSION :
      java version "10" 2018-03-20
      Java(TM) SE Runtime Environment 18.3 (build 10+46)
      Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      macOS High Sierra 10.13.3

      A DESCRIPTION OF THE PROBLEM :
      TreeView will take an exponential time for the number of additional items in the root grandchild item.

      This is because the TreeView.getRow(TreeUtil.getRow) method is called excessively exponentially when there are selected nodes when adding multiple items.

      Therefore, this workaround is to clear the selection before adding and return it after the addition.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Execute the test
      2) Open the grandchild node of the Root node

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      It operates with wait time of at most a few seconds
      ACTUAL -
      It seems to freeze

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      import javafx.application.Application;
      import javafx.beans.property.StringProperty;
      import javafx.collections.ObservableList;
      import javafx.scene.Scene;
      import javafx.scene.control.TextArea;
      import javafx.scene.control.TreeItem;
      import javafx.scene.control.TreeView;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.StackPane;
      import javafx.stage.Stage;

      public final class TreeViewPerformanceTest extends Application{
      private static boolean USE_WORKAROUND = false;
      private static final int DATA_SIZE = 1000*1000;
      private static final int TREE_DATA_SIZE = 1000*100;

      private StringProperty reportProperty;
      private TreeView<String> treeView;

      @Override
      public void start(Stage primaryStage) throws Exception {
      final TextArea report = new TextArea();
      this.reportProperty = report.textProperty();
      buildTreeView();
      BorderPane borderPane = new BorderPane();
      borderPane.setCenter(new StackPane(treeView));
      borderPane.setBottom(report);

      final Scene scene = new Scene(borderPane, 800, 800);
      primaryStage.setScene(scene);
      primaryStage.sizeToScene();
      primaryStage.show();
      }

      private void buildTreeView() {
      Integer[] d1a = new Integer[DATA_SIZE];
      for(int i=0; i<d1a.length; i++) {
      d1a[i] = i;
      }
      this.treeView = new TreeView<String>();
      treeView.setFixedCellSize(25);
      final LazyLoadTreeItem treeItem = new LazyLoadTreeItem("Node");
      treeItem.setExpanded(true);
      treeView.setRoot(treeItem);
      treeView.setEditable(false);

      if(USE_WORKAROUND) {
      treeView.expandedItemCountProperty().addListener((ob,oldValue,newValue)->{
      int scrollToIndex = treeView.getSelectionModel().getSelectedIndex();
      treeView.scrollTo(scrollToIndex);
      });
      }
      }

      private class LazyLoadTreeItem extends TreeItem<String>{
      LazyLoadTreeItem(String title){
      super(title);
      }
      @Override
      public ObservableList getChildren() {
      if(this.loaded) {
      return super.getChildren();
      }
      long t = System.currentTimeMillis();
      this.loaded = true;
      final String value = getValue();

      final LazyLoadTreeItem[] d1a = new LazyLoadTreeItem[TREE_DATA_SIZE];
      for(int i=0; i<d1a.length; i++) {
      d1a[i] = new LazyLoadTreeItem(value + "-" + String.valueOf(i));
      }
      final ObservableList<TreeItem<String>> children = super.getChildren();
      TreeItem<String> selectedTreeItem = treeView.getSelectionModel().getSelectedItem();

      if(USE_WORKAROUND) {
      treeView.getSelectionModel().clearSelection();
      children.setAll(d1a);
      int scrollToIndex = treeView.getRow(selectedTreeItem);
      treeView.scrollTo(scrollToIndex);
      treeView.getSelectionModel().select(selectedTreeItem);
      }else {
      children.setAll(d1a);
      }

      String result = value + ": time: " + (System.currentTimeMillis() - t);
      reportProperty.set( reportProperty.get() + "\n" + result );
      return children;
      }

      @Override
      public boolean isLeaf() {
      return false;
      }


      boolean loaded;
      }

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

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Rewrite the test code as follows

      USE_WORKAROUND = true

        Attachments

          Activity

            People

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

              Dates

              • Created:
                Updated: