cursive icon indicating copy to clipboard operation
cursive copied to clipboard

[BUG] Views not visible (or hidden) slow ScrollView down significantly

Open TaaviE opened this issue 1 year ago • 4 comments

Describe the bug I think ScrollView slows down exponentially based on the content inside, even if that content isn't visible, or is hidden.

To Reproduce I have this layout hierarchy right now (naming excluded):

> ResizedView
    > LinearLayout
        > PaddedView (header)
           > TextView
           > HideableView (hidden)
               > ScrollView
                   > DebugView
           > HideableView (hidden)
               > ScrollView
                   > LoggerView
        > ResizedView
          > AlignedView
             > ScrollView
                 > LinearLayout
                     > PaddedView
                        > TextView
** Repeating element **
                 > LinearLayout (one section containing a title and a list of (expandable) items)
                     > TextView (section header basically)
                     > HideableView (might be hidden)
                         > ScrollView
                             > ListView
                                 > TextView
** Repeating element **
    > PaddedView (footer)
        > TextView

Expected behavior Faster draws if only 40 lines of text are actually displayed, and approximately 1000 in all the visible views.

Environment

  • Operating system used: Ubuntu 22.04
  • Backend used: crossterm
  • Current locale: en_GB.UTF-8
  • Cursive version: 0.20.0 (crates.io)

TaaviE avatar Dec 02 '22 14:12 TaaviE

It seems like the largest amount of time is spent in <cursive_core::views::linear_layout::LinearLayout as cursive_core::view::view_trait::View>::required_size and cursive_core::views::text_view::TextView::compute_rows I will try replacing LinearLayout with something else and see if things improve as I can't get rid of the TextViews.

TaaviE avatar Dec 05 '22 12:12 TaaviE

Performance increased tremendously without any behavior changes when I wrapped the repeating element's ScrollView in LastSizeView, but it's still around 1fps and TextView::compute_rows still seems to dominate the flamegraph.

It seems weird that the rows are constantly recomputed when the internal text doesn't change. Can't there be a cache that is purged if the string within a TextView is changed? At least ListView should probably cache the size of its labels.

TaaviE avatar Dec 05 '22 15:12 TaaviE

Hi,

Indeed, LinearLayout, and especially nested LinearLayouts, may not be very cache-friendly.

TextView does have some rows cache, but the issue is that LinearLayout currently has a multi-pass layout phase, which (especially when nested) can result in many size requests to the TextView with different sizes, which doesn't play well with the single cache in TextView.

A short-term solution could be to keep multiple cached sizes in TextView, to be more robust to the various requests sent by LinearLayout.

Another option would be to have a more limited LinearLayout, possibly less flexible, but with a more efficient layout phase.

A longer-term solution would be to rework the View contract to allow LinearLayout to run in a single pass, but I'm not entirely sure how to get that yet.

Performance increased tremendously without any behavior changes when I wrapped the repeating element's ScrollView in LastSizeView

That's... very surprising! As you can see here, SizeView does not really change any behavior on the wrapped view.

gyscos avatar Dec 05 '22 16:12 gyscos

Hi

Another option would be to have a more limited LinearLayout, possibly less flexible, but with a more efficient layout phase.

Are there any alternatives that could be used right now? All I'd like to achieve is a scrollable list of scrollable lists (of text) that wouldn't bring Cursive to its knees.

That's... very surprising! As you can see here, SizeView does not really change any behavior on the wrapped view.

I just noticed it went from being frozen to very low framerate once I made that change. Maybe it's just the effect it had on some other element in the hierarchy or compilation.

TaaviE avatar Dec 05 '22 16:12 TaaviE