⚡ perf: Improve performance of RebuildTree() by 68%#3895
Conversation
WalkthroughRefactors the Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–60 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
Summary of ChangesHello @gaby, 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 focuses on improving the efficiency and memory management of the routing tree construction within the application. It refactors the Highlights
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 pull request introduces a significant performance improvement to the buildTree function by refactoring the logic for allocating and populating routing buckets. The new implementation is more efficient, using fewer loops and pre-allocating memory for slices, which eliminates the need for a separate deduplication step. The code is now cleaner and easier to understand. The addition of the Benchmark_App_RebuildTree benchmark is also a valuable contribution, allowing for easy measurement of the performance gains from this optimization. Overall, this is an excellent change that improves both performance and maintainability.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3895 +/- ##
==========================================
- Coverage 91.71% 91.66% -0.05%
==========================================
Files 115 115
Lines 9967 9982 +15
==========================================
+ Hits 9141 9150 +9
- Misses 527 532 +5
- Partials 299 300 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR optimizes the tree bucket allocation algorithm in the routing system by eliminating redundant intermediate data structures and improving memory efficiency. The refactoring removes the need for deduplication while preserving optimal preallocation.
Key changes:
- Replaced two-pass allocation strategy with single-pass approach using computed prefix paths
- Eliminated
uniqueRouteStackcall by preventing duplicates during distribution - Added
Benchmark_App_RebuildTreeto measure tree rebuild performance
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| router.go | Refactored buildTree() to compute treePaths upfront and preallocate buckets with exact capacities, eliminating intermediate map and deduplication step |
| router_test.go | Added benchmark for RebuildTree() method to measure performance of tree reconstruction |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
router_test.go (1)
1457-1469: Benchmark correctly exercises repeated RebuildTree callsThe benchmark setup looks sound: routes are registered once, alloc reporting is enabled, and each
b.Loop()iteration forces a full rebuild by flippingroutesRefreshedbefore callingRebuildTree(). This should give a clean signal on rebuild cost without extra noise.If you ever want to make the intent clearer, you could wrap the
routesRefreshedassignment in a tiny helper (e.g.markRoutesDirtyForTest) rather than poking the field directly, but that’s purely cosmetic here.router.go (1)
712-754: Single-pass buildTree preserves routing semantics and orderingThe new single-pass
buildTreelogic looks correct:
- Per-method, every route ends up in exactly the buckets it needs (global routes in all buckets including
0, prefix-specific routes only in their 3‑byte prefix bucket).- For each bucket, routes appear in the same relative order as in
app.stack[method](globals + matching-prefix routes), so handler/middleware ordering is preserved.- Bucket
0intentionally contains only “global” routes, and thenext/nextCustomfallback totreeStack[method][0]stays correct because any route that could match a path whose hash doesn’t share its 3‑byte static prefix is treated as global (treePath == 0).If you want to make this behavior future-proof for maintainers, consider adding a short comment near the
tsMap[0]initialization explaining that bucket0is reserved for prefix-agnostic routes and is the fallback when no prefix bucket exists.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
router.go(1 hunks)router_test.go(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Agent
- GitHub Check: lint
- GitHub Check: unit (1.25.x, macos-latest)
- GitHub Check: unit (1.25.x, windows-latest)
- GitHub Check: Compare
- GitHub Check: repeated
|
@gaby the range benchmark checks are failing because of the data type
|
|
I need to debug the local version. Unfortunately, we don't have any tests that check the internal structure, so we can't be sure that nothing has been applied incorrectly here. |
|
@ksw2000 Is the entry for 0 still necessary? I don't think it's used anymore, but I'm not sure. I think I added that back then for routes that have less than 3 characters or the root "/" route. |




Summary
Before
After
Benchstat