This is an automated email from the ASF dual-hosted git repository.

papegaaij pushed a commit to branch wicket-6774
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/wicket-6774 by this push:
     new 338720c7fc WICKET-6774: benchmark a real ajax behavior, and hand out 
behavior ids first
338720c7fc is described below

commit 338720c7fc3390a4746239ed1f31e65ca0f49e36
Author: Emond Papegaaij <[email protected]>
AuthorDate: Fri Sep 4 22:48:03 2026 +0200

    WICKET-6774: benchmark a real ajax behavior, and hand out behavior ids first
    
    Every behavior shape so far used AttributeModifier, which never needs a 
stable
    id, so none of them created the BehaviorIdList that stores those ids. That 
is
    the structure this issue claims its largest saving on, and it was the one 
case
    the benchmarks did not cover. AJAX_BEHAVIOR adds a real AjaxEventBehavior, 
so
    the numbers are comparable to the -36.2% serialized saving reported on the
    issue in 2020; measured now it is -39.8% for the tree, -72 bytes of retained
    heap and -32 bytes serialized per component.
    
    Keeping STABLE_ID_BEHAVIOR alongside it is deliberate. The absolute saving 
is
    the same for both, because the same structure is removed either way, but the
    bare behavior carries almost nothing of its own and so reports -86% per
    component against the real behavior's -68%. Having both makes it obvious 
that
    the absolute figure is the one that carries over between cases and the
    percentage is not.
    
    readBehaviorById could not run at all before this. It looked up an id that 
was
    never handed out, which the array index of the reworked state resolves 
happily
    while master throws InvalidBehaviorIdException, since master only builds its
    BehaviorIdList when getBehaviorId is called. The setup now assigns ids 
first,
    the way rendering does, so the benchmark measures the same work on both.
    
    With that fixed, the ajax paths measure (2 forks, ns/op, master -> reworked
    state):
    
        readBehaviorById                 2.82 ->  1.62   -43%
        readBehaviors[AJAX_BEHAVIOR]    11.15 ->  1.97   -82%,  72 -> 24 B/op
        readMetaData[AJAX_BEHAVIOR]      1.06 ->  0.81   -24%
        buildAndDetach[AJAX_BEHAVIOR]   51.59 -> 29.36   -43%, 180 -> 96 B/op
    
    Meta data reads get cheaper as a side effect: master keeps the id list in 
the
    component's own meta data, so any meta data read on a link or ajax component
    pays to walk past it.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 .../wicket/benchmarks/ComponentStateBenchmark.java | 49 +++++++++++++++++++---
 1 file changed, 43 insertions(+), 6 deletions(-)

diff --git 
a/wicket-benchmarks/src/main/java/org/apache/wicket/benchmarks/ComponentStateBenchmark.java
 
b/wicket-benchmarks/src/main/java/org/apache/wicket/benchmarks/ComponentStateBenchmark.java
index c43fd50976..b44b5a66af 100644
--- 
a/wicket-benchmarks/src/main/java/org/apache/wicket/benchmarks/ComponentStateBenchmark.java
+++ 
b/wicket-benchmarks/src/main/java/org/apache/wicket/benchmarks/ComponentStateBenchmark.java
@@ -21,6 +21,8 @@ import java.util.concurrent.TimeUnit;
 import org.apache.wicket.AttributeModifier;
 import org.apache.wicket.Component;
 import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.model.Model;
@@ -99,24 +101,37 @@ public class ComponentStateBenchmark
                 * biggest saving. None of the other shapes exercise it.
                 */
                STABLE_ID_BEHAVIOR(false, false, false, true),
-               MODEL_STABLE_ID_BEHAVIOR(true, false, false, true);
+               MODEL_STABLE_ID_BEHAVIOR(true, false, false, true),
+               /**
+                * A real {@link AjaxEventBehavior}, so the figure is 
comparable to the -36.2% serialized
+                * saving reported on WICKET-6774. {@link #STABLE_ID_BEHAVIOR} 
isolates the id storage but
+                * carries almost nothing of its own, which flatters the 
percentage.
+                */
+               AJAX_BEHAVIOR(false, false, false, true, true);
 
                private final boolean model;
                private final boolean behavior;
                private final boolean metaData;
                private final boolean stableId;
+               private final boolean ajax;
 
                Shape(boolean model, boolean behavior, boolean metaData)
                {
-                       this(model, behavior, metaData, false);
+                       this(model, behavior, metaData, false, false);
                }
 
                Shape(boolean model, boolean behavior, boolean metaData, 
boolean stableId)
+               {
+                       this(model, behavior, metaData, stableId, false);
+               }
+
+               Shape(boolean model, boolean behavior, boolean metaData, 
boolean stableId, boolean ajax)
                {
                        this.model = model;
                        this.behavior = behavior;
                        this.metaData = metaData;
                        this.stableId = stableId;
+                       this.ajax = ajax;
                }
 
                Component newComponent(String id)
@@ -142,7 +157,7 @@ public class ComponentStateBenchmark
                        }
                        if (stableId)
                        {
-                               Behavior stable = new StableIdBehavior();
+                               Behavior stable = ajax ? new AjaxTestBehavior() 
: new StableIdBehavior();
                                c.add(stable);
                                // rendering a callback url does this; it is 
what materialises the id storage
                                c.getBehaviorId(stable);
@@ -150,6 +165,22 @@ public class ComponentStateBenchmark
                }
        }
 
+       /** A real ajax behavior, with the fields and callback machinery that 
implies. */
+       private static class AjaxTestBehavior extends AjaxEventBehavior
+       {
+               private static final long serialVersionUID = 1L;
+
+               AjaxTestBehavior()
+               {
+                       super("change");
+               }
+
+               @Override
+               protected void onEvent(AjaxRequestTarget target)
+               {
+               }
+       }
+
        /** Requires a stable behavior id, the way an ajax behavior or link 
does. */
        private static class StableIdBehavior extends Behavior
        {
@@ -222,9 +253,15 @@ public class ComponentStateBenchmark
                        WicketContext.attach();
                        component = new WebMarkupContainer("c");
                        component.setDefaultModel(Model.of("m"));
-                       component.setMetaData(KEY, "v");
-                       component.add(AttributeModifier.replace("class", "a"),
-                               AttributeModifier.replace("style", "b"), 
AttributeModifier.replace("title", "c"));
+                       // ids have to be handed out before they can be looked 
up: master only builds its
+                       // BehaviorIdList when getBehaviorId is called, and 
throws
+                       // InvalidBehaviorIdException otherwise. Rendering a 
callback url does this.
+                       for (int i = 0; i < 3; i++)
+                       {
+                               Behavior stable = new StableIdBehavior();
+                               component.add(stable);
+                               component.getBehaviorId(stable);
+                       }
                }
 
                @TearDown(Level.Trial)

Reply via email to