Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Please ask technical questions in the appropriate category. Thank you!

Performance issues in JavaFX 8 when adding or removing children

2948362May 12 2015 — edited Nov 16 2015

I'm working on an application that needs to display a pretty big amount of information at once about a lot of different objects. The application was originally made using Java 7 and JavaFX 2.2 and everything has been working fine up until now. However, recently some users upgraded to Java 8 and they noticed severe performance issues that has made the application unusable. After lots of testing, we managed to find that the issue was whenever nodes were added or removed using parent.getChildren().remove(..) or parent.getChildren().add(...), and so on. In JavaFX 8, calls to these methods often take around 1/10th of a second and often several seconds, compared to basically 0 in JavaFX 2.2.


Here is some code to demonstrate the issue. It simply adds some VBoxes inside other VBoxes, and then adds lots of Labels to them. It then prints the time it took to execute:


package javafx;

import javafx.application.Application;

import javafx.application.Platform;

import javafx.beans.binding.Bindings;

import javafx.scene.Node;

import javafx.scene.Scene;

import javafx.scene.control.Label;

import javafx.scene.control.ScrollPane;

import javafx.scene.layout.ColumnConstraints;

import javafx.scene.layout.GridPane;

import javafx.scene.layout.VBox;

import javafx.stage.Stage;

import java.util.ArrayList;

import java.util.List;

public class JavaFXTest extends Application {

  VBox innerBox, anotherBox;

  VBox outerBox;

  ScrollPane scroll;

  public JavaFXTest() {

  scroll = new ScrollPane();

  innerBox = new VBox();

  anotherBox = new VBox();

  outerBox = new VBox();

  final ColumnConstraints left = new ColumnConstraints();

  final ColumnConstraints right = new ColumnConstraints();

  left.setPercentWidth(100);

  right.percentWidthProperty().bind(Bindings.subtract(100, left.percentWidthProperty()));

  GridPane grid = new GridPane();

  grid.setHgap(5);

  grid.getColumnConstraints().addAll(left, right);

  grid.add(innerBox, 0, 0);

  grid.add(anotherBox, 0, 1);

  outerBox.getChildren().add(grid);

  scroll.setContent(outerBox);

  }

  private void runTest(Stage stage) {

  Scene scene = new Scene(scroll);

  stage.setScene(scene);

  stage.show();

  System.out.println("JavaFXTest version: " + com.sun.javafx.runtime.VersionInfo.getRuntimeVersion());

  final List<Node> nodes = new ArrayList<Node>();

  for (int i = 0; i < 10; i++) {

  VBox box = new VBox();

  nodes.add(box);

  for (int j = 0; j < 100; j++) {

  box.getChildren().add(new Label(j + ""));

  }

  }

  long started = System.currentTimeMillis();

  innerBox.getChildren().addAll(nodes);

  long total = System.currentTimeMillis() - started;

  System.out.println("Time spent: " + total);

  }

  public static void main(String[] args) {

  JavaFXTest.launch(args);

  }

  @Override

  public void start(Stage stage) throws Exception {

  JavaFXTest test = new JavaFXTest();

  test.runTest(stage);

  }

}

Building and running this yields vastly different results, depending on which JavaFX version is used. As you can see, it only measures the time taken to call innerBox.getChildren().addAll(nodes), and for some reason that's very different.

Here's my output for two executions of the program:

JavaFX version: 8.0.45-b11

Time spent: 123

JavaFX version: 2.2.51-b13

Time spent: 5

That is not a fluke, the times are that different no matter how many times I try. And this time difference only gets worse the more complex the elements you are trying to add or remove are. I don't have much experience using JavaFX, so I would very much appreciate it if someone could help me understand what is going on. Why is the time it takes to execute that code so much longer when the only difference is the version of JavaFX? Is there a way to work around this, or do I need to rewrite large parts of the application simply to make it behave the same way as before?

Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Dec 14 2015
Added on May 12 2015
9 comments
13,103 views