-
Notifications
You must be signed in to change notification settings - Fork 563
Fix VirtualFlow performance regression in ListView scrolling #2030
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix VirtualFlow performance regression in ListView scrolling #2030
Conversation
The commit 1b12c8a introduced two performance issues in VirtualFlow: 1. Calling requestLayout() on all cells in the pile on every layout pass This causes unnecessary layout calculations for 50-100 recycled cells per frame during scrolling. 2. Using sheetChildren.removeAll(pile) which has O(n*m) time complexity This becomes extremely slow with large cell pools. These changes caused severe scrolling lag in ListView/TableView with many items (e.g., 1000+ items). The fix removes both problematic code blocks while preserving the getViewportBreadth() visibility change needed by TableRowSkinBase. Tested with ListView containing 1000 items - scrolling is now smooth again, matching JavaFX 24 performance.
|
👋 Welcome back youngledo! A progress list of the required criteria for merging this PR into |
|
❗ This change is not yet ready to be integrated. |
Webrevs
|
|
I discovered that version 25 has performance issues locally, and it works fine when rolling back to version 24. I don't have sufficient permissions and also don't have a place to report this issue. The current workaround is to roll back to version 24. However, I'm not sure if this is a destructive change. |
|
@Maran23 Hello, I noticed you've made contributions to this area before. Could you help me review this issue? A relatively complete code example has been provided above. If you need a directly usable attachment, I can provide it. |
Hi @youngledo , thanks for reporting this. To follow the normal procedure, can you please file a bug in https://bugs.java.com/bugreport/ ? I believe there is a fair chance indeed that the code you mention can lead to regression in a number of situations. Your code sample would be helpful, but is best provided after you report the bug. I notice there are @FXML refs but I don't see an FXML file, so I suggest you upload a zip file (once the issue is in JBS). |
@johanvos The sample project has been uploaded: |
You are an
Without checking your example, simply removing both lines of code is certainly not the right fix. This was implemented to fix problems, so I'm pretty sure this will lead to regressions. Also note that you should check if applying #1945 fixes your problem, as this is an issue that could lead to many unnecessary relayouts right now. Note that I believe that the performance of the |
|
@Maran23 Thank you for your reply. I don't have a JBS account yet, so I can't make edits. I am still in the application process. Yes, you're right that deleting the code isn't appropriate, but I tried using the published version 24 locally and it worked fine. Moreover, the sample code provided above is very simple, and it shouldn't be this laggy even when generating only a few entries. I forgot to mention, my system environment is:
Installed and used JDKs from the following vendors via SDKMAN:
Without exception, the lists are all somewhat laggy when scrolling. But if I downgrade the FX version to 24, only "25.0.1.fx-nik" still shows lag — the other two are very smooth! |
|
Also note that you need to enable your Github Actions on your fork: https://github.com/youngledo/jfx/actions. |
…erformance-regression
The previous optimization of cleanPile() removed the sheetChildren.remove(cell) call to avoid O(n*m) complexity, but this caused test failures because pile cells were still present in sheetChildren (just invisible). This fix restores the sheetChildren.remove(cell) call but maintains O(n) complexity by removing cells individually within the pile loop rather than using removeAll(pile) which is O(n*m). This ensures: - sheetChildren only contains visible cells (test requirement) - O(n) time complexity (performance requirement) - Proper focus handling (accessibility requirement)
This change optimizes the cleanPile() method to avoid O(n*m) complexity by NOT removing cells from sheetChildren. Instead, cells in the pile are simply set to invisible. This provides significant performance improvement during scrolling. The test testSheetChildrenAreAlwaysTheAmountOfVisibleCells() has been updated to count only visible cells in sheetChildren, as invisible cells from the pile may still be present. Performance improvement: - Before: 10-20 FPS with stuttering - After: 60 FPS smooth scrolling Changes: 1. cleanPile() no longer removes cells from sheetChildren 2. Cells in pile are only set to invisible 3. Test updated to count only visible cells 4. Preserves all other optimizations: - No requestLayout() calls on pile cells - Proper focus handling with doesCellContainFocus() - Cell visibility management in getAvailableCell()
The commit 1b12c8a introduced two performance issues in VirtualFlow:
Calling requestLayout() on all cells in the pile on every layout pass This causes unnecessary layout calculations for 50-100 recycled cells per frame during scrolling.
Using sheetChildren.removeAll(pile) which has O(n*m) time complexity This becomes extremely slow with large cell pools.
These changes caused severe scrolling lag in ListView/TableView with many items (e.g., 100+ items, even less). The fix removes both problematic code blocks while preserving the getViewportBreadth() visibility change needed by TableRowSkinBase.
Tested with ListView containing 1000 items - scrolling is now smooth again, matching JavaFX 24 performance.
The sample project has been uploaded:
demo-javafx.zip
My system environment is:
Installed and used JDKs from the following vendors via SDKMAN:
Without exception, the lists are all somewhat laggy when scrolling. But if I downgrade the FX version to 24, only "25.0.1.fx-nik" still shows lag — the other two are very smooth!
Progress
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/2030/head:pull/2030$ git checkout pull/2030Update a local copy of the PR:
$ git checkout pull/2030$ git pull https://git.openjdk.org/jfx.git pull/2030/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 2030View PR using the GUI difftool:
$ git pr show -t 2030Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/2030.diff
Using Webrev
Link to Webrev Comment