Conversation
A development aid, kept in the default reactor so the benchmarks keep compiling against the current API. It is never released and has no unit tests; the README covers how to run it. The component benchmarks used to investigate WICKET-6774 only ever existed as attachments on the issue, and they no longer compile: WicketTester has moved to its own module, and since JDK 23 javac no longer runs annotation processors found on the classpath, so JMH silently produces no BenchmarkList and the run executes nothing. Keeping them in the reactor means they keep compiling. It holds JMH benchmarks for component state, page rendering, resource name iteration and page serialization, a ComponentFootprint tool that reports retained heap through JOL and serialized size per state shape, and WicketContext as the shared harness. Backported from master. PageEncryptionBenchmark is left out: it measures SchemeCrypt and ICryptScheme, which this branch does not have. Locale.of() is Java 19, so the benchmark uses new Locale() here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A component's flexible state - model, behaviors and meta data - is no longer an Object[] with a packing convention but a ComponentState instance. One final class rather than one subclass per combination: the combinations all cost the same 24 bytes on a 64 bit VM with compressed oops, so specialised classes save nothing, while four implementations of the same six accessors make every unpacking call site megamorphic and stop it from being inlined. A behavior's id is now its index in that state rather than a position in a BehaviorIdList kept in the component's meta data, which removes the list entirely. Reading meta data on a link or ajax component gets cheaper as a side effect, because it no longer has to walk past that entry. Behaviour change: behavior ids are only maintained for stateful behaviors. Ids can change for other behaviors, also when combined on the same component. AbstractDefaultAjaxBehavior no longer forces an id at bind time; an id is add order by construction now, and forcing one would fix the behavior positions of every ajax-enabled component for its whole life. Backported from master. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ResourceStreamLocator walks a list of candidate filenames for every property and markup lookup, once per registered properties loader. Misses are the common case, because a key is resolved by climbing the component hierarchy, so every class above the one that declares it contributes a full traversal that finds nothing. toString() built each candidate from four prepend() calls, and the locale part went through getLocale(), which builds a Locale, even though LocaleResourceNameIterator.next() had just built the identical suffix and thrown it away. It now keeps that suffix, and caches the Locale per state for the one caller that does read it back. Verified by enumeration rather than by argument: every candidate name with its locale, style, variation and extension over 6 paths x 2 styles x 2 variations x 7 locales x 5 extension lists x strict/non-strict, 9918 names, byte-identical before and after. One note for reviewers: toString() now takes the locale segment from next() instead of from getLocale(). A subclass supplied through the protected newLocaleResourceNameIterator hook that overrode getLocale() without also overriding next() would see a difference; nothing in the tree does that. Backported from master. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ResourceUtil#rejectPathSeparators ran Locale#toString() on every call, and Locale#toString() builds a new string each time. Every resource lookup validates the locale, so that is once per lookup for a result that is thrown away. Without a variant, a script or extensions, Locale#toString() returns nothing but the language and the country joined by '_', so inspecting those two subtags directly is equivalent and allocates nothing. Richer locales are rare and still take the general route, which also keeps the two in agreement about the subtags that toString() drops. Verified by enumeration over 4918 locales: byte-identical outcomes before and after. Backported from master. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
JavaSerializer wrote into a java.io.ByteArrayOutputStream with no initial size, which starts at 32 bytes and grows by copying everything written so far into a buffer of twice the size. A page of any substance outgrows that several times over, and every one of those copies is thrown away again immediately. Wicket already has a ByteArrayOutputStream that chains a new buffer instead. Starting it at 4kB means a modest page never has to grow it at all. Measured over a page of 500 components, 37924 bytes serialized: 256714 -> 214763 bytes allocated per operation, -16%. Backported from master. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.