Skip to content

Commit 4c48958

Browse files
authored
perf: Refactor with optimizations (#41)
* chore: Prepare for perf work — quiet test logging and ignore perf/ Lower com.retailsvc test logging from debug to info to avoid skewing load-test profiles, ignore perf/ artifacts, and mark the completed refactor plan as done. * perf: Cache Spec.basePath at construction (W1) basePath() was previously recomputed via URI.create on every request through RequestPreparationFilter.stripBasePath. The result is spec-static, so promote it to a record component populated in Spec.from(...). Eliminates ~100 MB of URI allocations and ~26 CPU samples per JFR run; k6 throughput +2.6% (44.2k -> 45.3k rps), p95 -40 µs. * 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. * perf: Pre-build ref->component index in Spec (W3) resolveSchema/resolveParameter previously rebuilt the component name via String.substring on every call. Build a Map keyed by the full $ref string at construction time so resolution is a single lookup with no per-request allocation. Removes ~150 MB of String/byte[] allocs per JFR run; tightens the validator hot path when schemas use \$ref. * perf: Skip parseQuery when no QUERY parameters (W4) validateParameters previously allocated a HashMap and ran String.split on every request, even when the operation declared no query parameters (the common case). Defer the parse to the first QUERY parameter encountered; routes without query params now skip the work entirely. k6 throughput +3.3% (44.1k -> 45.5k rps), p95 -22 us. * perf: Precompute Parameter JSON-pointer at parse time (W5) The validation pointer "/<in>/<name>" was rebuilt with StringBuilder on every request per parameter, even though it's spec-static. Promote it to a record component computed once in the convenience constructor and read it in RequestPreparationFilter.validateParameters. k6 throughput +4.6% vs baseline (44.2k -> 46.2k rps), p95 -83 us. * perf: Add Request.current() escape hatch (W7) Each Request.bytes()/parsed()/operationId()/pathParams() call walks the JDK scope chain independently. Document and expose Request.current() so handlers that read more than one field can hoist the lookup. Pure addition — no hot-path callers in the library or example code, so no measured throughput delta on the k6 baseline. * fix: Address SonarQube findings in Spec Use LinkedHashMap.newLinkedHashMap(int) for properly-sized init and reuse the PARAMETER_REF_PREFIX constant in resolveParameterOrParse instead of duplicating the literal.
1 parent aff17a0 commit 4c48958

9 files changed

Lines changed: 252 additions & 196 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ build/
3636

3737
### Claude Code per-developer settings ###
3838
.claude/settings.local.json
39+
40+
### Performance recordings ###
41+
perf/

0 commit comments

Comments
 (0)