Skip to content

ListView: Poor performance with many variable-extent items + jumpTo (scroll bar, trackpad, mouse wheels) #52207

@esDotDev

Description

@esDotDev

Related: #153085


Update September 2023:


Update from July 2023: #52207 (comment)


Update from September 2021: After much discussion, this #52207 (comment) suggestion emerged as a pretty good proposal. Basically, SliverList could short-circuit actually instantiating and laying out children if, once built, they are discovered to implement the PreferredHeight protocol. The next step is to implement this. -@Hixie


[√] Flutter (Channel master, v1.15.4-pre.241, on Microsoft Windows [Version 10.0.18362.657], locale en-US)

Here is an example (~80 lines) of a 10,000 item ListView, which attempts to uses a simple scrollbar to drive scroll position:
https://gist.github.com/esDotDev/792425c2cdfef947ce514b8ab70511e6

The performance is very poor on all platforms, Desktop, Web, Android, even when using profile mode on Android. iOS has not been tested.

I'm seeing frame render times up to 1300ms on Windows 10, with a Ryzen 3700x. Android, in profile mode, with a Snapdragon 845, has similar results. Visually, you can easily produce a 2-3 second lag by just scrolling up and down a couple of times.
http://screens.gskinner.com/shawn/2020-03-08_12-57-31.mp4

Setting the .itemExtent property solves the problem, but severely limits the flexibility of the list, no expanding cards, no ability to size rows to content, etc.

Problem in a nutshell
We need the ability to have many list items, of variable height, while retaining the ability to set scroll position efficiently. This is especially important on Web and Desktop which typically use scrollbars to traverse lists.

Proposed Solutions

  1. It would be nice if the list could handle this itself, seems like it calculates maxExtents each frame, when we really only need it calculating when the size of something has changed. Potentially this could be exposed so we could call it manually (scrollController.calculateExtents()) when we know something is changing.

  2. As a simpler workaround, you could expose .maxExtents so I as the programmer of the list can specify max extents with some basic math. ie, if I know my open cards are 40px heigh, and my closed are 20px, I can track open/close cards, and provide the list with the max extents very quickly, without it needing to measure.

  3. Could potentially leverage PreferredSizeWidget to reduce the calculation costs for the list. Then each list item can return it's own size, and the developer can come up with novel ways to reduce that calculation cost. For example, I could have my closed items all return a hardcoded value, while my "expanded items" use a LayoutBuilder to calculate their height. Or I could simply have multiple hardcoded values, and return the right one depending on the state of the renderer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: desktopRunning on desktopc: performanceRelates to speed or footprint issues (see "perf:" labels)customer: crowdAffects or could affect many people, though not necessarily a specific customer.f: scrollingViewports, list views, slivers, etc.found in release: 3.16Found to occur in 3.16found in release: 3.18Found to occur in 3.18frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onperf: speedPerformance issues related to (mostly rendering) speedteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions