[performance] Reduce per-request overhead in hot path#2559
Conversation
Cache route match result across lifecycle phases using private fields on JavalinServletContext, add single-pass matchAndExtract() to PathParser, replace lowercase() allocations with ignoreCase comparisons, and swap LinkedList for ArrayList in Endpoints. All changes are internal — no public API modifications. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2559 +/- ##
============================================
- Coverage 86.29% 86.24% -0.05%
+ Complexity 1509 1507 -2
============================================
Files 155 155
Lines 4348 4356 +8
Branches 523 525 +2
============================================
+ Hits 3752 3757 +5
- Misses 363 366 +3
Partials 233 233 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Add `inline` to cachedHttpHandler/cachedWillMatch to eliminate lambda allocations - Use primitive Int (0/1/-1) for boolean cache to avoid boxing overhead - Use @PublishedApi for UNSET sentinel to support inline access Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
08bb8a4 to
d8cf339
Compare
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
augment review |
🤖 Augment PR SummarySummary: Reduces per-request overhead in Javalin’s request lifecycle hot path by avoiding repeated route lookups and string allocations. Changes:
Tests: Adds a lifecycle test intended to cover cache hit and miss paths. 🤖 Was this summary useful? React with 👍 or 👎 |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
augment review |
| fun `router heavily exercises caching across lifecycle phases`() = TestUtil.test(Javalin.create { cfg -> | ||
| // Setup before/after filters to force the router to evaluate the endpoint multiple times | ||
| // during the same request lifecycle, triggering the cache hits. | ||
| cfg.routes.before("/*") { ctx -> ctx.attribute("req_start", true) } |
There was a problem hiding this comment.
This test sets up routes.before/routes.after (BEFORE/AFTER), which won’t necessarily evaluate the new cachedWillMatch logic that’s only used in BEFORE_MATCHED/AFTER_MATCHED. If the goal is to exercise caching “across lifecycle phases”, consider ensuring the test actually triggers BEFORE_MATCHED/AFTER_MATCHED behavior so the cache paths are covered.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Bumps `javalin.version` from 7.0.1 to 7.1.0. Updates `io.javalin:javalin-bundle` from 7.0.1 to 7.1.0 Release notes *Sourced from [io.javalin:javalin-bundle's releases](https://github.com/javalin/javalin/releases).* > 7.1.0 > ----- > > What's Changed > -------------- > > * Bump com.fasterxml.jackson.core:jackson-core from 2.21.0 to 2.21.1 by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2543](https://redirect.github.com/javalin/javalin/pull/2543) > * [deps]: Bump the dependencies group across 1 directory with 17 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2545](https://redirect.github.com/javalin/javalin/pull/2545) > * [websocket] Fix WebSocket over HTTP/2 Extended Connect (RFC 8441) by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2547](https://redirect.github.com/javalin/javalin/pull/2547) > * fix(README): update artifactId for SSL plugin in `README.md` by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * Add `wsExceptionHandler` to `MicrometerPlugin` for WebSocket exception tagging by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2557](https://redirect.github.com/javalin/javalin/pull/2557) > * [rendering] jte - introduce directoryTemplateEngine for (6.x-like), rename default to classPathTemplateEngine by [`@elwin013`](https://github.com/elwin013) in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > * Add javalin-bom module by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2558](https://redirect.github.com/javalin/javalin/pull/2558) > * [performance] Reduce per-request overhead in hot path by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2559](https://redirect.github.com/javalin/javalin/pull/2559) > * [performance] Eliminate per-request regex and allocation overhead by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2560](https://redirect.github.com/javalin/javalin/pull/2560) > > New Contributors > ---------------- > > * [`@yvasyliev`](https://github.com/yvasyliev) made their first contribution in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * [`@elwin013`](https://github.com/elwin013) made their first contribution in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.0.1...javalin-parent-7.1.0> Commits * [`e458dba`](javalin/javalin@e458dba) [maven-release-plugin] prepare for next development iteration * [`9766d2f`](javalin/javalin@9766d2f) [maven-release-plugin] prepare release javalin-parent-7.1.0 * [`12acf0b`](javalin/javalin@12acf0b) [performance] Eliminate per-request regex and allocation overhead ([#2560](https://redirect.github.com/javalin/javalin/issues/2560)) * [`f6a1e40`](javalin/javalin@f6a1e40) [performance] Reduce per-request overhead in hot path * [`1e59eda`](javalin/javalin@1e59eda) [pom] Add javalin-bom module ([#2558](https://redirect.github.com/javalin/javalin/issues/2558)) * [`b43f37a`](javalin/javalin@b43f37a) [rendering] jte - introduce directoryTemplateEngine for (6.x-like behavior) * [`72b2320`](javalin/javalin@72b2320) [micrometer] Add `wsExceptionHandler` to `MicrometerPlugin` * [`37c91c4`](javalin/javalin@37c91c4) [readme] Update artifactId for SSL plugin * [`9acf45e`](javalin/javalin@9acf45e) [cleanup] Use Header constants * [`0289084`](javalin/javalin@0289084) [headers] Add missing headers to Header.kt * Additional commits viewable in [compare view](javalin/javalin@javalin-parent-7.0.1...7.1.0) Updates `io.javalin.community.openapi:javalin-openapi-plugin` from 7.0.1 to 7.1.0 Release notes *Sourced from [io.javalin.community.openapi:javalin-openapi-plugin's releases](https://github.com/javalin/javalin-openapi/releases).* > 7.1.0 > ----- > > **Changes** > > * [javalin/javalin-openapi#275](https://redirect.github.com/javalin/javalin-openapi/issues/275) [Make ClassLoader used for loading resources configurable](javalin/javalin-openapi@de1b6b7) > * Support Javalin 7.1.0 > > **Sponsors** > Thanks to everyone who supported me this month 💜 > > **Minimal requirements** > > * Java 17+ / Kotlin 2.3+ > * Javalin 7.1.0 Commits * [`5388862`](javalin/javalin-openapi@5388862) [GH-275](https://redirect.github.com/javalin/javalin-openapi/issues/275) Cover missing resource loaders and release 7.1.1-rc.1 * [`cbbc8d0`](javalin/javalin-openapi@cbbc8d0) [GH-276](https://redirect.github.com/javalin/javalin-openapi/issues/276) Release 7.1.0 (Resolves [#276](https://redirect.github.com/javalin/javalin-openapi/issues/276)) * [`de1b6b7`](javalin/javalin-openapi@de1b6b7) [GH-275](https://redirect.github.com/javalin/javalin-openapi/issues/275) Make ClassLoader used for loading resources configurable (Resolves [#275](https://redirect.github.com/javalin/javalin-openapi/issues/275)) * See full diff in [compare view](javalin/javalin-openapi@7.0.1...7.1.0) Updates `io.javalin.community.openapi:javalin-swagger-plugin` from 7.0.1 to 7.1.0 Release notes *Sourced from [io.javalin.community.openapi:javalin-swagger-plugin's releases](https://github.com/javalin/javalin-openapi/releases).* > 7.1.0 > ----- > > **Changes** > > * [javalin/javalin-openapi#275](https://redirect.github.com/javalin/javalin-openapi/issues/275) [Make ClassLoader used for loading resources configurable](javalin/javalin-openapi@de1b6b7) > * Support Javalin 7.1.0 > > **Sponsors** > Thanks to everyone who supported me this month 💜 > > **Minimal requirements** > > * Java 17+ / Kotlin 2.3+ > * Javalin 7.1.0 Commits * [`5388862`](javalin/javalin-openapi@5388862) [GH-275](https://redirect.github.com/javalin/javalin-openapi/issues/275) Cover missing resource loaders and release 7.1.1-rc.1 * [`cbbc8d0`](javalin/javalin-openapi@cbbc8d0) [GH-276](https://redirect.github.com/javalin/javalin-openapi/issues/276) Release 7.1.0 (Resolves [#276](https://redirect.github.com/javalin/javalin-openapi/issues/276)) * [`de1b6b7`](javalin/javalin-openapi@de1b6b7) [GH-275](https://redirect.github.com/javalin/javalin-openapi/issues/275) Make ClassLoader used for loading resources configurable (Resolves [#275](https://redirect.github.com/javalin/javalin-openapi/issues/275)) * See full diff in [compare view](javalin/javalin-openapi@7.0.1...7.1.0) Updates `io.javalin:javalin-micrometer` from 7.0.1 to 7.1.0 Release notes *Sourced from [io.javalin:javalin-micrometer's releases](https://github.com/javalin/javalin/releases).* > 7.1.0 > ----- > > What's Changed > -------------- > > * Bump com.fasterxml.jackson.core:jackson-core from 2.21.0 to 2.21.1 by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2543](https://redirect.github.com/javalin/javalin/pull/2543) > * [deps]: Bump the dependencies group across 1 directory with 17 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2545](https://redirect.github.com/javalin/javalin/pull/2545) > * [websocket] Fix WebSocket over HTTP/2 Extended Connect (RFC 8441) by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2547](https://redirect.github.com/javalin/javalin/pull/2547) > * fix(README): update artifactId for SSL plugin in `README.md` by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * Add `wsExceptionHandler` to `MicrometerPlugin` for WebSocket exception tagging by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2557](https://redirect.github.com/javalin/javalin/pull/2557) > * [rendering] jte - introduce directoryTemplateEngine for (6.x-like), rename default to classPathTemplateEngine by [`@elwin013`](https://github.com/elwin013) in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > * Add javalin-bom module by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2558](https://redirect.github.com/javalin/javalin/pull/2558) > * [performance] Reduce per-request overhead in hot path by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2559](https://redirect.github.com/javalin/javalin/pull/2559) > * [performance] Eliminate per-request regex and allocation overhead by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2560](https://redirect.github.com/javalin/javalin/pull/2560) > > New Contributors > ---------------- > > * [`@yvasyliev`](https://github.com/yvasyliev) made their first contribution in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * [`@elwin013`](https://github.com/elwin013) made their first contribution in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.0.1...javalin-parent-7.1.0> Commits * [`e458dba`](javalin/javalin@e458dba) [maven-release-plugin] prepare for next development iteration * [`9766d2f`](javalin/javalin@9766d2f) [maven-release-plugin] prepare release javalin-parent-7.1.0 * [`12acf0b`](javalin/javalin@12acf0b) [performance] Eliminate per-request regex and allocation overhead ([#2560](https://redirect.github.com/javalin/javalin/issues/2560)) * [`f6a1e40`](javalin/javalin@f6a1e40) [performance] Reduce per-request overhead in hot path * [`1e59eda`](javalin/javalin@1e59eda) [pom] Add javalin-bom module ([#2558](https://redirect.github.com/javalin/javalin/issues/2558)) * [`b43f37a`](javalin/javalin@b43f37a) [rendering] jte - introduce directoryTemplateEngine for (6.x-like behavior) * [`72b2320`](javalin/javalin@72b2320) [micrometer] Add `wsExceptionHandler` to `MicrometerPlugin` * [`37c91c4`](javalin/javalin@37c91c4) [readme] Update artifactId for SSL plugin * [`9acf45e`](javalin/javalin@9acf45e) [cleanup] Use Header constants * [`0289084`](javalin/javalin@0289084) [headers] Add missing headers to Header.kt * Additional commits viewable in [compare view](javalin/javalin@javalin-parent-7.0.1...7.1.0) Updates `io.javalin:javalin-testtools` from 7.0.1 to 7.1.0 Release notes *Sourced from [io.javalin:javalin-testtools's releases](https://github.com/javalin/javalin/releases).* > 7.1.0 > ----- > > What's Changed > -------------- > > * Bump com.fasterxml.jackson.core:jackson-core from 2.21.0 to 2.21.1 by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2543](https://redirect.github.com/javalin/javalin/pull/2543) > * [deps]: Bump the dependencies group across 1 directory with 17 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2545](https://redirect.github.com/javalin/javalin/pull/2545) > * [websocket] Fix WebSocket over HTTP/2 Extended Connect (RFC 8441) by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2547](https://redirect.github.com/javalin/javalin/pull/2547) > * fix(README): update artifactId for SSL plugin in `README.md` by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * Add `wsExceptionHandler` to `MicrometerPlugin` for WebSocket exception tagging by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2557](https://redirect.github.com/javalin/javalin/pull/2557) > * [rendering] jte - introduce directoryTemplateEngine for (6.x-like), rename default to classPathTemplateEngine by [`@elwin013`](https://github.com/elwin013) in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > * Add javalin-bom module by [`@Copilot`](https://github.com/Copilot) in [javalin/javalin#2558](https://redirect.github.com/javalin/javalin/pull/2558) > * [performance] Reduce per-request overhead in hot path by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2559](https://redirect.github.com/javalin/javalin/pull/2559) > * [performance] Eliminate per-request regex and allocation overhead by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2560](https://redirect.github.com/javalin/javalin/pull/2560) > > New Contributors > ---------------- > > * [`@yvasyliev`](https://github.com/yvasyliev) made their first contribution in [javalin/javalin#2556](https://redirect.github.com/javalin/javalin/pull/2556) > * [`@elwin013`](https://github.com/elwin013) made their first contribution in [javalin/javalin#2551](https://redirect.github.com/javalin/javalin/pull/2551) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.0.1...javalin-parent-7.1.0> Commits * [`e458dba`](javalin/javalin@e458dba) [maven-release-plugin] prepare for next development iteration * [`9766d2f`](javalin/javalin@9766d2f) [maven-release-plugin] prepare release javalin-parent-7.1.0 * [`12acf0b`](javalin/javalin@12acf0b) [performance] Eliminate per-request regex and allocation overhead ([#2560](https://redirect.github.com/javalin/javalin/issues/2560)) * [`f6a1e40`](javalin/javalin@f6a1e40) [performance] Reduce per-request overhead in hot path * [`1e59eda`](javalin/javalin@1e59eda) [pom] Add javalin-bom module ([#2558](https://redirect.github.com/javalin/javalin/issues/2558)) * [`b43f37a`](javalin/javalin@b43f37a) [rendering] jte - introduce directoryTemplateEngine for (6.x-like behavior) * [`72b2320`](javalin/javalin@72b2320) [micrometer] Add `wsExceptionHandler` to `MicrometerPlugin` * [`37c91c4`](javalin/javalin@37c91c4) [readme] Update artifactId for SSL plugin * [`9acf45e`](javalin/javalin@9acf45e) [cleanup] Use Header constants * [`0289084`](javalin/javalin@0289084) [headers] Add missing headers to Header.kt * Additional commits viewable in [compare view](javalin/javalin@javalin-parent-7.0.1...7.1.0) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- Dependabot commands and options You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Summary
Surgical optimizations to Javalin's request lifecycle hot path — 8 files changed, +55/-19 lines, all internal with no public API modifications.
findHttpHandlerEntriesis called once per request instead of 3-4 times, cached in a private field onJavalinServletContext(not request attributes)matchAndExtract()combines match + extract in one regex execution instead of threeignoreCase = trueinstead oflowercase()string allocationTest plan
mvn test -pl javalin— 972 tests, 0 failures)🤖 Generated with Claude Code