Repository navigation
Optimize Router matching with prefix Trie filter - #509
Conversation
Also added more specific tests to validate behavior of soon-to-come trie perf improvement
This commit replaces the (N)$ linear route iteration with a fast-path Trie filter. Instead of checking every registered route's RegExp against the incoming request, the Router now builds a prefix tree using the literal, non-variable segments of each route. When a request is received, the Router walks the Trie to collect only routes that exactly match the static prefix of the request path. It then evaluates the original RegExp match only on those isolated candidates. This provides (L)$ routing candidate filtration for massive APIs while maintaining 100% exact backward compatibility (preserving exact regex extraction, nested routers, and exact positional priority). Performance Metrics (10k routes across 100 controllers): | Metric | Before (Linear) | After (Trie) | Speedup | | :--- | :--- | :--- | :--- | | Worst-Case Match | 902.19 μs | 3.20 μs | ~281x Faster | | 404 (Not Found) | 734.12 μs | 0.45 μs | ~1,631x Faster |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a major performance optimization to the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This is an excellent optimization that significantly improves routing performance by using a Trie to filter route candidates. The implementation is well-done, maintaining backward compatibility with routing priorities and behavior. The new Trie data structure is implemented cleanly and the integration into the existing Router is seamless. I have one suggestion to improve the readability and simplify the logic in the Trie.add method.
Also added more specific tests to validate behavior of soon-to-come trie perf improvement
# Conflicts: # pkgs/shelf_router/benchmark/router_benchmark.dart # pkgs/shelf_router/pubspec.yaml
jonasfj
left a comment
There was a problem hiding this comment.
I think this is correct.
We could do better. But this is not bad.
| class RouterEntry { | ||
| @internal | ||
| final class RouterEntry { | ||
| static int _nextIndex = 0; |
There was a problem hiding this comment.
This is a bit dangerous.. because if a RouterEntry isn't immediately added to the trie, we risk having a problem with this index and ordering.
We could consider giving trie as an argument to the constructor.. so that creating an instance also always adds it to the trie.
And then we have a natural place to put a comment that explains why this is important.
There was a problem hiding this comment.
I considered moving RouterEntry to trie.dart (or maybe the other way around) and making the ctor private so the Trie always manages lifetime.
Would you prefer that? It's just code motion, mostly.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a significant performance optimization to the routing mechanism by replacing the linear scan of routes with a Trie-based filtering approach. The implementation correctly builds a prefix tree from the static parts of the routes and uses it to quickly select a small set of candidate routes for full regex matching. This drastically improves performance, especially for applications with many routes, as demonstrated by the provided metrics. The changes maintain backward compatibility by preserving the route registration order for matching priority. The new Trie implementation is well-structured and includes new tests to validate its behavior. Overall, this is an excellent improvement.
…ter entry - Add `.github/workflows/post_summaries.yaml` and `write-comments: false` in `publish.yaml` so `Health` and `Publish` workflow summaries are posted on PRs. - Configure `license_test_string` and `license` in `.github/workflows/health.yaml` to avoid false-positive warnings on 2-space copyright headers. - Add the missing `## 1.1.5-wip` entry in `pkgs/shelf_router/CHANGELOG.md` for #509 (`Optimize Router matching with prefix Trie filter`).
…5, and shelf_static 1.2.0 (#546) * chore: add health workflow and missing shelf_static changelog entry - Add `.github/workflows/health.yaml` calling `dart-lang/ecosystem/.github/workflows/health.yaml`. - Add the missing `CHANGELOG.md` entry under `## 1.2.0-wip` in `pkgs/shelf_static/CHANGELOG.md` for #507 (`feat(static): modernize directory listing UI`). * chore: add post_summaries.yaml, license config, and missing shelf_router entry - Add `.github/workflows/post_summaries.yaml` and `write-comments: false` in `publish.yaml` so `Health` and `Publish` workflow summaries are posted on PRs. - Configure `license_test_string` and `license` in `.github/workflows/health.yaml` to avoid false-positive warnings on 2-space copyright headers. - Add the missing `## 1.1.5-wip` entry in `pkgs/shelf_router/CHANGELOG.md` for #509 (`Optimize Router matching with prefix Trie filter`). * chore: prepare shelf 1.4.3, shelf_router 1.1.5, and shelf_static 1.2.0 releases - Document `toSecondResolution` microsecond truncation in `pkgs/shelf_static/CHANGELOG.md`. - Drop `-wip` suffix from `shelf` (`1.4.3`), `shelf_router` (`1.1.5`), and `shelf_static` (`1.2.0`). * chore(shelf): rename tools/ to tool/ to satisfy pub publish validation
This commit replaces the (N)$ linear route iteration with a fast-path Trie filter.
Instead of checking every registered route's RegExp against the incoming request,
the Router now builds a prefix tree using the literal, non-variable segments of each route.
When a request is received, the Router walks the Trie to collect only routes
that exactly match the static prefix of the request path. It then evaluates
the original RegExp match only on those isolated candidates.
This provides (L)$ routing candidate filtration for massive APIs while maintaining
100% exact backward compatibility (preserving exact regex extraction, nested routers,
and exact positional priority).
Performance Metrics (10k routes across 100 controllers):