On Wed, 17 Jun 2026 08:54:10 GMT, Marius Hanl <[email protected]> wrote:

> This PR is an optimization for `Node.styleClass` and `Parent.stylesheets`.
> Instead of always initializing both properties with an empty list, we are 
> creating (therefore allocating) the list on the first access instead.
> Similar to many other lazy properties.
> 
> Why?
> - `Parent.getStylesheets()` is very rarely used by developers and JavaFX 
> code. So this list is very often completely unused and empty. Most developers 
> usually only add stylesheets at the `Scene`
> - `Node.getStyleClass()` is usually not used (empty) for layout containers 
> such as `Pane` or `Group` or shapes. A JavaFX App usually consists of a good 
> amount of such containers (or shapes)
> 
> So that our CSS code is not initializing both lists on access, I added 
> related `NodeHelper` and `ParentHelper` methods to return `null` when both 
> lists were not initialized and therefore used. Otherwise we return the list 
> as before.
> This will save us some memory and allocation, which is both good for the 
> memory consumption but also for `Node` / `Parent` creation (time).
> 
> Added documentation and tests. Will do some measurements with some apps very 
> soon and attach it here.
> 
> ---
> 
> # Benchmarks
> 
> I wrote a very small scene graph analyzer snippet to measure the memory gain.
> Feel free to test this on your own apps!
> 1. Get the `SceneGraphAnalyzer` here: 
> [SceneGraphAnalyzer](https://gist.github.com/Maran23/38beca5b043e547e1a84749e3162c0b2)
> 2. Add this code to your `Scene` and press the shortcut `F12` when all of the 
> UI is loaded:
> 
>         scene.setOnKeyPressed(event -> {
>             if (event.getCode() == KeyCode.F12) {
>                 var analyzer = new SceneGraphAnalyzer();
>                 var res = analyzer.analyze(scene);
>                 res.print();
>             }
>         });
> 
> 3. If you have a modular app, add the following VM argument: `--add-opens 
> javafx.graphics/javafx.scene=yourapp`
> 
> ## Projects
> 
> 1. Tested with 
> [JFXCentral](https://github.com/dlsc-software-consulting-gmbh/jfxcentral2)
> 
> 
> ╔══════════════════════════════════════════════════╗
> ║ Scene Graph Analysis                             ║
> ╠══════════════════════════════════════════════════╣
> ║  Total nodes:                 654                ║
> ║    ├─ Parent nodes:           388                ║
> ║    └─ Leaf nodes:             266                ║
> ╠══════════════════════════════════════════════════╣
> ║  Null styleClass:         19 /  654  (  2.9%)    ║
> ║  Null stylesheets:       386 /  388  ( 99.5%)    ║
> ╠══════════════════════════════════════════════════╣
> ║  Saved (styl...

I tested this in an app with lots of 2D shapes:


╔══════════════════════════════════════════════════╗
║ Scene Graph Analysis                             ║
╠══════════════════════════════════════════════════╣
║  Total nodes:               6,836                ║
║    ├─ Parent nodes:         4,850                ║
║    └─ Leaf nodes:           1,986                ║
╠══════════════════════════════════════════════════╣
║  Null styleClass:      2,048 / 6,836  ( 30.0%)   ║
║  Null stylesheets:     4,845 / 4,850  ( 99.9%)   ║
╠══════════════════════════════════════════════════╣
║  Saved (styleClass):      144.00 KB              ║
║  Saved (stylesheets):     340.66 KB              ║
║  Saved (total):           484.66 KB              ║
║                   (at 72 bytes / empty list)     ║
╚══════════════════════════════════════════════════╝


`Node`s with null styleClass are indeed mainly containers and `Shape`s.
I'd say it's worth doing both optimizations.

-------------

PR Comment: https://git.openjdk.org/jfx/pull/2191#issuecomment-4743050065

Reply via email to