Skip to content

Commit 6155853

Browse files
thcedclaude
andcommitted
perf: Memoise compiled regex Pattern in DefaultValidator (W2)
validateString recompiled Pattern on every request. Pattern is immutable and thread-safe; cache compiled instances in a ConcurrentHashMap keyed by the raw pattern string. Cache is bounded by the spec's distinct pattern count. Removes ~215 MB of int[]/Matcher allocations per JFR run and the ~31 CPU samples in validateString. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3adf1cb commit 6155853

1 file changed

Lines changed: 8 additions & 1 deletion

File tree

src/main/java/com/retailsvc/http/validate/DefaultValidator.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.Objects;
3030
import java.util.Set;
3131
import java.util.UUID;
32+
import java.util.concurrent.ConcurrentHashMap;
33+
import java.util.concurrent.ConcurrentMap;
3234
import java.util.function.Function;
3335
import java.util.regex.Pattern;
3436

@@ -37,6 +39,7 @@ public final class DefaultValidator implements Validator {
3739
private static final String FORMAT_KEYWORD = "format";
3840

3941
private final Function<String, Schema> refResolver;
42+
private final ConcurrentMap<String, Pattern> compiledPatterns = new ConcurrentHashMap<>();
4043

4144
public DefaultValidator(Function<String, Schema> refResolver) {
4245
this.refResolver = refResolver;
@@ -81,7 +84,11 @@ private void validateString(Object value, StringSchema s, String pointer) {
8184
if (s.maxLength() != null && str.length() > s.maxLength()) {
8285
fail(pointer, "maxLength", "string longer than " + s.maxLength(), str);
8386
}
84-
if (s.pattern() != null && !Pattern.compile(s.pattern()).matcher(str).matches()) {
87+
if (s.pattern() != null
88+
&& !compiledPatterns
89+
.computeIfAbsent(s.pattern(), Pattern::compile)
90+
.matcher(str)
91+
.matches()) {
8592
fail(pointer, "pattern", "does not match pattern " + s.pattern(), str);
8693
}
8794
if (s.enumValues() != null && !s.enumValues().contains(str)) {

0 commit comments

Comments
 (0)