Performance Fix: Solving Quadratic Slowdown in svelte-table#6266
Performance Fix: Solving Quadratic Slowdown in svelte-table#6266Abyanzhafran wants to merge 3 commits into
Conversation
📝 WalkthroughWalkthroughThe PR introduces a new ChangesOption Merging with flatMerge Utility
Estimated Code Review Effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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 |
🎯 Changes
Fixes #6235
Performance Fix: Solving Quadratic Slowdown in
svelte-tableRoot Cause Analysis (RCA)
The performance degradation observed in the Svelte 5 adapter was caused by a nested getter chain created during rapid reactive updates.
mergeObjectsutility (inherited from SolidJS patterns) creates a proxy-like object using lazy getters. These getters do not resolve values eagerly; instead, they walk through asourcesarray via a closure every time a property is read.createTable.svelte.ts, the$effect.preblock callssetOptionson every reactive tick (e.g., every keystroke in a filter input). Each call tosetOptionswraps the previous options object in a new layer ofmergeObjects.table.optionsbecomes an N-deep chain of closures. Reading a value that lives in the base defaults (like feature configurations) requires traversing all N layers.The Solution: Eager Resolution with
flatMergeIntroduced a new utility,
flatMerge, to break the recursion chain in hot reactive paths.flatMergevsmergeObjectsmergeObjects(Lazy): Preserves getters. Great for initial setup where you want to maintain a "live" link to reactive state.flatMerge(Eager): Resolves all values immediately and copies them into a plain, flat JavaScript object. This transforms the lookup complexity from O(N) back to O(1).Implementation Strategy
I implemented a targeted fix that preserves reactivity while eliminating the slowdown:
mergeObjectsis still used during the initial table setup to ensure the adapter correctly "captures" Svelte's reactive getters.$effect.preloop and themergeOptionshandler, we switched toflatMerge.$effect.prere-runs automatically when dependencies change, we don't need the resulting object to have getters; the effect itself acts as the "pump" that pushes fresh, flat data into the table core.Performance Impact
Code Summary
This fix ensures
@tanstack/svelte-tableremains performant even in complex tables with rapid state changes, while maintaining full compatibility with Svelte 5's reactivity model.How to reproduce in our local env
pnpm linkto connect into your reproducible project✅ Checklist
pnpm test:pr.Summary by CodeRabbit