Repository navigation
Conversation
Hold the violations of a constraint in a plain list with a containment check, as it typically holds a single violation, and the violations of a validation in a plain field. Without the Lazy holders, getResults() also compiles small enough for C2 to inline it into its caller, so that a validation that finds no work to do allocates nothing.
- Cache descriptors keyed by the runtime (possibly proxy) class of the validated object, so that each validation needs one map lookup instead of unwrapping the class and then looking up its descriptor. - Stop writing to a ConcurrentHashMap on every bean descriptor cache hit. - Resolve the root bean descriptor once per validation rather than once in hasWork() and again for the base frame.
- Cache Groups#asStrategy() instead of building a new composite strategy for every validation. - Cache the hash codes of group strategies, which key per-strategy caches. - Cache the groups computed for a single explicitly requested group, so that validating a group does not re-resolve it on every call.
Field#get and Method#invoke take a slow path when the reflective object is not a JIT constant, which is the case for descriptors held in caches. Reflection remains the fallback, with the same exception wrapping.
- Record each constraint's initialized validator on its descriptor, so the factory-wide validator cache is consulted once per constraint. - Look up cached unwrapping information before going through computeIfAbsent.
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.
Summary
Removes repeated lookups that every
validate()call performed.Evidence
Numbers are JMH throughput (
-p provider=bval -f 2 -wi 2 -i 3, 1 s iterations,-prof gc, JDK 25), measured against the PR below this one. The machine was busy, so throughput carries wide error bars; the bytes allocated per operation (B/op) are deterministic.All benchmarks
getResults()over C2's inline size limit (failed to inline: already compiled into a big method).bvalNoConstraintsthen drops from 114M to 49M ops/s and starts allocating 88 B/op. With the results change it stays at 0 B/op.Merge Danger
Door: two-way
Blast Radius: property access
MethodHandles and fall back to reflection when no handle can be created. Exceptions are wrapped as before (IllegalArgumentException, around anInvocationTargetExceptionfor getters).jsr303.bvalBuildFactory/bvalBootstrapAndValidateshow drops in this run with unchanged allocation; they recover in the PRs above, which points to noise.