On Thu, 10 Sep 2026 20:04:02 GMT, Andy Goryachev <[email protected]> wrote:

>> I fail to understand that. All methods in the `createStyleHelper` will use 
>> the parent chain we created once. How could we still end up being quadratic? 
>> We will go through the aprent chain, yes, but we did that before as well
>
> ok, this might be a contrived scenario, but it does illustrate the problem.  
> the test passes in master and fails with this PR:
> 
> 
>     @Test
>     void testQuadraticPerformace() {
>         scene.getStylesheets().add(toDataURL(
>             """
>             .old { -fx-padding: 11; }
>             .new { -fx-padding: 22; }
>             """));
> 
>         int depth = 50;
>         AtomicInteger count = new AtomicInteger();
> 
>         class TPane extends Pane {
>             private final SimpleStyleableObjectProperty<Font> font;
>             private final List<CssMetaData<? extends Styleable, ?>> metadata;
> 
>             public TPane(CssMetaData<TPane, Font> fontMetadata) {
>                 font = new SimpleStyleableObjectProperty<>(fontMetadata, 
> this, "font", Font.getDefault());
>                 // we should have a utility for this
>                 ArrayList<CssMetaData<? extends Styleable, ?>> md = new 
> ArrayList<>(Pane.getClassCssMetaData());
>                 md.add(fontMetadata);
>                 this.metadata = List.copyOf(md);
>                 getStyleClass().add("old");
>             }
> 
>             @Override
>             public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() 
> {
>                 return metadata;
>             }
>         }
> 
>         CssMetaData<TPane, Font> fontMD = new 
> FontCssMetaData<TPane>("-fx-font", Font.getDefault()) {
>             @Override
>             public StyleableProperty<Font> getStyleableProperty(TPane p) {
>                 count.incrementAndGet();
>                 return p.font;
>             }
>             
>             @Override
>             public boolean isSettable(TPane p) {
>                 return !p.font.isBound();
>             }
>         };
> 
>         ArrayList<TPane> panes = new ArrayList<>(depth);
>         TPane top = new TPane(fontMD);
>         panes.add(top);
> 
>         TPane p = top;
>         for (int i = 1; i < depth; i++) {
>             TPane ch = new TPane(fontMD);
>             p.getChildren().add(ch);
>             panes.add(ch);
>             p = ch;
>         }
> 
>         scene.setRoot(top);
>         top.applyCss();
> 
>         p.getChildren().add(new Pane());
> 
>         for (TPane pane : panes) {
>             pane.getStyleClass().setAll("new");
>         }
> 
>         count.set(0);
> 
>         p.getChildren().add(new Pane());
> 
>         int ct = count.get();
>         assertTrue(ct <= depth * 4, "Expected<=" + (depth*4) + " observed=" + 
> ct + " for depth=" + depth);
>     }

Just verified, works with my changes.

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

PR Review Comment: https://git.openjdk.org/jfx/pull/2225#discussion_r3983149969

Reply via email to