Commit 4c48958
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
- docs/superpowers/plans
- src
- main/java/com/retailsvc/http
- internal
- spec
- validate
- test
- java/com/retailsvc/http/internal
- resources
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
0 commit comments