Skip to content

refactor: No normalized path interning - #375

Merged
nielsenko merged 6 commits into
serverpod:mainfrom
nielsenko:refactor-no-normalized-path-interning
Aug 25, 2026
Merged

refactor: No normalized path interning#375
nielsenko merged 6 commits into
serverpod:mainfrom
nielsenko:refactor-no-normalized-path-interning

Conversation

@nielsenko

@nielsenko nielsenko commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Description

Remove NormalizedPath interning

This PR removes NormalizedPath interning completely.

Interning was originally added to avoid re-normalizing paths, but it always had two problems:

On top of that, the new NormalizedPath.fromSegments and NormalizedPath.fromUri constructors - now the ones actually used on the request path - made interning tricky, so the security PRs (#369 & #371) simply skipped it for those paths.

Most of the lost performance is recouped by:

  • Pre-computing repeated work.
  • Extracting parameters into a single mutable map with undo-in-place during backtracking. Previously a copy was made at each parameter level so backtracking could just throw it away, but undoing in place avoids the copy and the allocation, reducing GC pressure.
  • Inferring from the registered routes whether backtracking is needed at all, and taking a faster non-backtracking walk when it isn't.

Results

┌────────┬─────────┬─────────┬────────────┐
│ routes │ Router  │ Spanner │ Routingkit │
├────────┼─────────┼─────────┼────────────┤
│ 1M     │ 1229 ns │ 1393 ns │ 3468 ns    │
├────────┼─────────┼─────────┼────────────┤
│ 100k   │ 994 ns  │ 1015 ns │ 3194 ns    │
├────────┼─────────┼─────────┼────────────┤
│ 10k    │ 579 ns  │ 402 ns  │ 1889 ns    │
└────────┴─────────┴─────────┴────────────┘
(measured on a 2.4 GHz 8-core Intel Core i9)

Fixes: #118 (not by improving caching, but by dropping it)
Fixes: #342 (this time by disabling interning altogether, instead of making caching opt-out)
Closes: #344 (investigation done)

Breaking changes

  • NormalizedPath.interned is removed

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 25dca879-e925-49f3-8c7c-4e2af097957f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nielsenko nielsenko self-assigned this Aug 20, 2026
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.72%. Comparing base (a623f2d) to head (ca653c6).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #375      +/-   ##
==========================================
- Coverage   92.74%   92.72%   -0.02%     
==========================================
  Files         110      110              
  Lines        4687     4702      +15     
  Branches     2373     2380       +7     
==========================================
+ Hits         4347     4360      +13     
- Misses        340      342       +2     
Flag Coverage Δ
relic_core 92.68% <100.00%> (-0.03%) ⬇️
relic_io 93.11% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

NormalizedPath drops the interned cache and hence the caching strategy
can no longer be set via the static NormalizedPath.interned property.

Cache (and LruCache/NoCache) stay for static_handler.
- fromUri reuses the unmodifiable Uri.pathSegments list when the path needs no
  normalization.
- Precompute each parameter Symbol at registration instead of per lookup.
- _lookupRecursive threads one mutable params map with undo on backtrack
  instead of copying it at each level.
@nielsenko
nielsenko force-pushed the refactor-no-normalized-path-interning branch from 4365a02 to c4cba4d Compare August 20, 2026 11:16
@nielsenko
nielsenko marked this pull request as ready for review August 21, 2026 16:32
@nielsenko
nielsenko requested a review from FXschwartz August 21, 2026 16:32
Comment thread packages/relic_core/lib/src/router/path_trie.dart Outdated
Comment thread packages/relic_core/lib/src/router/path_trie.dart Outdated
Comment thread packages/relic_core/lib/src/router/no_cache.dart
Comment thread packages/relic_core/test/router/no_cache_test.dart Outdated
@nielsenko
nielsenko force-pushed the refactor-no-normalized-path-interning branch from c4cba4d to deaad11 Compare August 24, 2026 07:34
Also drops the assertion that lookup results are not memoized, which is
still a valid future optimization.
@nielsenko
nielsenko force-pushed the refactor-no-normalized-path-interning branch from e2007fb to d840b0d Compare August 24, 2026 07:46
@nielsenko
nielsenko requested a review from FXschwartz August 24, 2026 07:49

@FXschwartz FXschwartz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🚀

@nielsenko
nielsenko merged commit 4742098 into serverpod:main Aug 25, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants