I'm trying to implement my own VirtualFlow but I'm having some performance issues and I don't understand where the bottleneck could be and what I could do to improve it.
Here's a showcase with two lists, one with simple cells and one with checkboxes too, both have 100_000 items (sorry for the gif quality):
As you can see, I have no issues scrolling through simple cells with just a label, but the list with checkboxes can be quite laggy at the beginning.
To reach such performance (would be much worse otherwise) I memoize my cell factory function so that all cells are ready in memory when needed, I was wondering if there's anything else to make it even faster/smoother.
The code I use to show the cells is:
long start = System.currentTimeMillis();
builtNodes.clear();
for (int i = from; i <= to; i++) {
C cell = cellForIndex.apply(i);
Node node = cell.getNode();
builtNodes.add(node);
}
manager.virtualFlow.container.getChildren().setAll(builtNodes);
long elapsed = System.currentTimeMillis() - start;
System.out.println("Show elapsed: " + elapsed);
I even added this little log, the heavy part seems to be when I call getChildren().setAll(...)
, both the cell building and the layout are almost immediate
Oh another note on the from
and to
parameters. When I scroll, I take the scrollbar's value and calculate the first and last visible indexes like this:
public int firstVisible() {
return (int) Math.floor(scrolled / cellHeight);
}
public int lastVisible() {
return (int) Math.ceil((scrolled + virtualFlow.getHeight()) / cellHeight - 1);
}
Edit to answer some questions:
Why implementing my own VirtualFlow?
The ultimate goal would be to make my own ListView implementation, in order to do that I also need a VirtualFlow, also I know it's a pretty low level and hard task, but I think it would be a good way to learn more about programming in general and about JavaFX too
Why memoization?
By caching the cell factory results in memory, it makes subsequent scrolls much faster since nodes are already built they just need to be laid out which is fairly easy. The issue is at the start because for some reason the VirtualFlow lags for more complex cells and I can't understand why since the popular library, Flowless, also uses memoization and caches the nodes in memory, but it is very fluent already from the start. JavaFX's VirtualFlow (revised from JFX16) is also very efficient without memoization, but it's much more complex to comprehend