Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested FlexLayout/BindableLayout Very Slow #12908

Closed
grumpymonk opened this issue Jan 25, 2023 · 4 comments
Closed

Nested FlexLayout/BindableLayout Very Slow #12908

grumpymonk opened this issue Jan 25, 2023 · 4 comments
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter layout-flex FlexLayout issues platform/iOS 🍎 platform/windows 🪟 s/needs-attention Issue has more information and needs another look t/bug Something isn't working

Comments

@grumpymonk
Copy link

Description

I am writing a desktop application for genealogy. In rendering the family tree, I am using two FlexLayouts (one inside the other) to create the visual representation of matrix data (list of list of an "ancestor"). The basic layout is as follows; I've omitted non-relevant data binding and property logic for brevity:

<ScrollView Orientation="Both">
    <Grid> <!-- grid sets desired height/width (computed in code-behind) so that the scrollview scrolls appropriately -->
        <FlexLayout BindableLayout.ItemsSource="{Binding Ancestors}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <FlexLayout BindableLayout.ItemsSource="{Binding .}">
                         <!-- .... data template ... -->
                    </FlexLayout>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </FlexLayout>
    </Grid>
</ScrollView>

This renders what I need, and the logic works. However, just showing five generations takes more than 5 seconds to draw. I know that fetching and generating the appropriate matrix takes less than 300ms, and the lag is definitely after the binding to "Ancestors" is made.

Since I need to be able to scroll on both the X and Y axes, using something like a CollectionView is not feasible, although it is noticeably faster. I also need to be able to click on any of the bound items in the inner template, so setting an inner CollectionView to "InputTransparent" is not a solution.

Note that the inner DataTemplate is another Grid with three Label components. So it is not an overly complex layout. Even a single Label within the inner template fails terribly in performance.

Steps to Reproduce

  1. Create a 2D array (e.g., List<List>) of data; use two for loops for any sort of data -- even a single string is fine
  2. Create a XAML layout similar to the one noted above
  3. Run the app
  4. Expectation: "Reasonable" rendering time, e.g., less than 2 seconds

    Observed: Extremely slow rendering, e.g., 5+ seconds for 5 generations of ancestry data.

    Link to public reproduction project repository

    n/a

    Version with bug

    7.0 (current)

    Last version that worked well

    Unknown/Other

    Affected platforms

    Windows, macOS

    Affected platform versions

    Windows 10/11, macOS Monterey+

    Did you find any workaround?

    No. I tried CollectionView (faster, but not feasible for this app due to reasons cited above), other BindableLayouts (e.g., VerticalStackLayout), and even manually populating a Grid in code-behind. It fails on the render every time.

    It would be nice if (as an alternative) CollectionView could have a property to disable scrolling, so that other input (e.g., Tap/Click) can be captured, the performance of CollectionView can be leveraged, but the scrolling can be handled "externally," such as with the top-level ScrollView.

    Relevant log output

    No response

@grumpymonk grumpymonk added the t/bug Something isn't working label Jan 25, 2023
@Eilon Eilon added legacy-area-perf Startup / Runtime performance area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter and removed legacy-area-perf Startup / Runtime performance labels Jan 25, 2023
@PureWeen PureWeen added the s/needs-repro Attach a solution or code which reproduces the issue label Jan 25, 2023
@ghost
Copy link

ghost commented Jan 25, 2023

Hi @grumpymonk. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@angelru
Copy link

angelru commented Jan 26, 2023

@grumpymonk
I also experience delays with nested FlexLayout, StackLayout and with CollectionView.

as here I say:
#12130

you can try:
https://github.com/Keflon/FunctionZero.Maui.Controls
https://github.com/Keflon/FunctionZero.Maui.Controls#treeviewzero

@ghost ghost added s/needs-attention Issue has more information and needs another look and removed s/needs-repro Attach a solution or code which reproduces the issue labels Jan 26, 2023
@grumpymonk
Copy link
Author

In the process of creating the repro project, I have (sheepishly) realized the root cause of the issue.

If, hypothetically, we were looking at a "generation" as only a predecessor's parents (no siblings, partners, etc.), then the best case scenario means that at 10 generations, a FlexLayout would be bound with up to 1024 entries to render. The documentation even says this is not optimal, and that a CollectionView type of control should be used. Compound that with also trying to simultaneously render the previous 9 generations, and that's why we end up waiting a very very long time.

When I switched the number of generations to show to up to 5, my widget updates fairly quickly (< 1.5s on average).

Unfortunately, while that is the answer to "why" I was observing such poor performance, this is still a bit of a problem. Is there a virtualization or lazy loading feature available within a BindableLayout, or/additionally a way to make a CollectionView disable handling scrolling?

Thanks for your time.

@jfversluis
Copy link
Member

Glad you figured out the root cause for your case at least. I think we have a couple of issues already on CollectionView related issues, also the one right above here so I will be closing this one to not duplicate efforts.

Right now there is no functionality for lazy loading a BindableLayout. From the docs:

While scrolling can be provided by wrapping a bindable layout in a ScrollView, this is not recommended as bindable layouts lack UI virtualization.

@jfversluis jfversluis closed this as not planned Won't fix, can't repro, duplicate, stale Jan 27, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Feb 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter layout-flex FlexLayout issues platform/iOS 🍎 platform/windows 🪟 s/needs-attention Issue has more information and needs another look t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants