On Mon, 7 Sep 2026 00:31:41 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                                          |
>>   +---------------------------------------------------------------+
>>   |  Nodes: 654 total, 388 parents, 266 leaves                    |
>>   +---------------------------------------------------------------+
>>   |   Field         Null   Total       %    N/A    Avg      Saved |
>>   |   ------------------------------------------...
>
> Marius Hanl has updated the pull request with a new target base due to a 
> merge or a rebase. The incremental webrev excludes the unrelated changes 
> brought in by the merge/rebase. The pull request contains eight additional 
> commits since the last revision:
> 
>  - Merge branch 'master' of https://github.com/openjdk/jfx into 
> 8386663-Stylesheet/StyleClass-list-should-be-lazily-initialized
>  - remove doc
>  - review comments
>  - improve tests
>  - Merge branch 'master' of https://github.com/openjdk/jfx into 
> 8386663-Stylesheet/StyleClass-list-should-be-lazily-initialized
>  - MenuItem toString() should also use the new styleClass way.
>    
>    TwoLevelFocusListBehavior was very weirdly relying on the toString() 
> behavior
>  - Move styleClass.toString into Node.toString()
>  - 8386663: Stylesheet/StyleClass list should be lazily initialized

modules/javafx.controls/src/main/java/javafx/scene/control/MenuItem.java line 
641:

> 639:             else sbuf.append(", ");
> 640:             sbuf.append("styleClass=");
> 641:             for (int i = 0; i < getStyleClass().size(); i++) {

You could replace all of that with `String.join(" ", getStyleClass())`.

modules/javafx.graphics/src/main/java/javafx/scene/Node.java line 8672:

> 8670:             else sbuf.append(", ");
> 8671:             sbuf.append("styleClass=");
> 8672:             for (int i = 0; i < getStyleClass().size(); i++) {

Same suggestion to use `String.join`.

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

PR Review Comment: https://git.openjdk.org/jfx/pull/2191#discussion_r3949972503
PR Review Comment: https://git.openjdk.org/jfx/pull/2191#discussion_r3950013171

Reply via email to