[two_dimensional_scrollables] [web] merged cells and span decorations has severe debug-mode scrolling jank
- Dominant language
- Dart
- Stars
- 179k
- Forks
- 31.1k
- PR merge metrics
- PR metrics pending
Description
I'm using the performance template, but here we have a problem in debug mode only.
It might sound minimal, but it's becoming *impossible* to use debug mode and this package altogether.
## steps to reproduce
I wrote a small repro using flutter `3.47.1`, but I also tested it on `master` with the same results.
1. clone https://github.com/lucavenir/two_dimensional_scrollable_debug_jank.
2. `flutter pub get`.
3. `flutter run -d chrome`.
4. scroll/drag the table vertically and diagonally.
5. repeat with `flutter run --profile -d chrome`.
### expected results
the table remains... usable, while scrolling; even in debug mode.
### actual results
scrolling in debug mode is severely janky. ~400-600ms.
the same table scrolls smoothly in profile and release modes.
## code sample
again, it's one small file (`main.dart`) in this repo: https://github.com/lucavenir/two_dimensional_scrollable_debug_jank
### implementation notes
notice how the cells are empty, so - AFAIK - there's nothing much the inner widgets are adding, performance wise.
instead, I focused on adding:
- merged rows;
- row and column `TableSpanDecoration`s;
- one pinned row and column;
- `cacheExtent: 0`;
- disabled automatic keep-alives and repaint boundaries.
the last two were made in an effort of minimizing jank. that didn't work out.
## performance profiling on master channel
- [x] The issue still persists on the master channel.
## Timeline Traces
NOTE. of course, this being a `debug` mode problem only, I only traced the debug build.
Timeline trace
[repro_trace.gz](https://github.com/user-attachments/files/31510427/repro_trace.gz)
the debug CPU profile points to several calls to `RenderTwoDimensionalViewport.parentDataOf` from the table's merged-cell decoration path - including `getRowRect`.
in a nutshell: `parentDataOf` has three `.containsValue`/`.contain` calls in an assertion. AFAICT these are three `O(n)` calls on debug mode. [link](
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/widgets/two_dimensional_viewport.dart#L883-L889). code (for brevity):
```dart
assert(
_children.containsValue(child) || // oof
_keepAliveBucket.containsValue(child) || // oof
_debugOrphans!.contains(child), // oof
);
```
[looks like](
https://github.com/flutter/packages/blob/main/packages/two_dimensional_scrollables/lib/src/table_view/table.dart#L1791-L1919) the table invokes `parentDataOf` repeatedly while splitting decorations around merged cells and calculating decorations and stuff.
## possible fix?
I'm not sure why or how to circumvent/fix this tbh.
for what's worth, a gemini agent suggested:
> Use Key-Based Lookup: Since `child.parentData` contains the `ChildVicinity`, Flutter can check `_children[child.parentData.vicinity] == child` in `O(1)` time instead of scanning `_children.containsValue(child)`.
but - again - I have no clue if this is a valid or pure schlop.
## What target platforms are you seeing this bug on?
web only.
the jank on e.g. macOS is not nearly as comparable.
## OS/Browser name and version | Device information
- macOS 26.6.2
- Chrome 152.0.7977.64
- MacBook Pro (Mac16,7), Apple M4 Pro, 24 GB memory
## Does the problem occur on emulator/simulator as well as on physical devices?
not really. AFAICT this reliably happens on the web only.
## Is the problem only reproducible with Impeller?
N/A
## Logs
no exceptions or error logs are ever emitted.
## Flutter Doctor output
Doctor output
(when not using master)
```console
[✓] Flutter (Channel stable, 3.47.1, on macOS 26.6.2 25G83 darwin-arm64, locale en-IT)
• Flutter version 3.47.1 on channel stable at /Users/venir/.local/share/mise/http-tarballs/7eab9d8e9ea4ffbfefee7c22f3287ade60a47bdd2aef1630e4d6f353a9b43dc1_strip_1
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 6655482ec0 (8 days ago), 2026-08-19 10:07:23 -0700
• Engine revision 5d53178869
• Dart version 3.13.1
• DevTools version 2.60.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0-rc1)
• Android SDK at /Users/venir/Library/Android/sdk
• Emulator version 35.2.10.0 (build_id 12414864) (CL:N/A)
• Platform android-36, build-tools 36.0.0-rc1
• Java binary at: /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java
• This JDK is specified in your Flutter configuration.
• Java version Java(TM) SE Runtime Environment (build 17.0.12+8-LTS-286)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.6)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17F113
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-arm64 • macOS 26.6.2 25G83 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 152.0.7977.64
[✓] Network resources
• No issues found!
```
Contributor guide
Research direction
Reproduce the issue from the linked repository's main.dart with Flutter web in debug and profile modes. Read RenderTwoDimensionalViewport.parentDataOf in packages/flutter/lib/src/widgets/two_dimensional_viewport.dart and the merged-cell decoration path in packages/two_dimensional_scrollables/lib/src/table_view/table.dart. Done means the reported debug-mode web scrolling jank is resolved without regressing the profile and release behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- performance, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100