Sunday, February 7, 2016

JavaFX TableView Performance: asObject()

In Dirk Lemmermanns JavaFX “Missing Features” Survey Results the two categories TableView and Performance are mentioned often by the JavaFX users.

Whilst performance of a TableView in JavaFX might not be perfect, it can often be improved by little effort.

For example in lots of JavaFX tutorials you find a snippet like the following:
myIntegerColumn.setCellValueFactory(cellData -> 
      cellData.getValue().myIntegerProperty().asObject());
This defines where the content of a cell should be taken from. In this example it is provided by an IntegerProperty, accessed with a method call to myIntegerProperty().
As an IntegerProperty is not directly usable with setCellValueFactory() (read here why), the property is often converted to an ObservableValue in the lambda expression with a call to asObject().

While this seems to be simple and correct - at least it works - this code contains a little problem. Every call to asObject() creates a new object. This is especially problematic if you e. g. sort a column with lots of rows.

E. g. on my laptop sorting a table with 50'000 rows takes a few seconds for the non-optimized columns. The columns using the pre-allocated asObject() sort in less then 50 milliseconds.

There is a little demo application available at https://github.com/belu/javafx-tableview-performance. There are two Integer and two Double columns with 50'000 rows. The "slow" columns use asObject() in the cellValueFactory. The "fast" columns use the pre-allocated asObject().