dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.04k stars 1.73k forks source link

Scrolling on a List View causes massive memory leak #23406

Closed ajsuydam closed 2 months ago

ajsuydam commented 3 months ago

Description

Unfortunately, providing repro code is going to be difficult, as this issue is presenting on an internal project.

However, I have a custom collection that is both observable and thread-safe (concurrent). I implemented it by adding INotifyCollectionChanged and INotifyPropertyChanged to a standard Collection<T>. It's very simple, no frills. Simply locks for reads and writes and implements busy waiting.

I have a ListView that is using that collection ("Messages") as it's ItemSource. There are hundreds to thousands of items in the collection. If I scroll on the collection, I get a runaway memory leak.

Here is the code for the ListView:

<ListView
    x:Name="LogConsole"
    CachingStrategy="RecycleElement"
    HasUnevenRows="False"
    HeightRequest="800"
    ItemsSource="{Binding Messages}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="mydatatype">
            <ViewCell>
                <Border BackgroundColor="Transparent">
                    <Grid Padding="10">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*" />
                            <ColumnDefinition Width="1*" />
                            <ColumnDefinition Width="1*" />
                            <ColumnDefinition Width="5*" />
                        </Grid.ColumnDefinitions>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <Label
                            Grid.Column="0"
                            FontAttributes="Bold"
                            Text="{Binding Peroperty1, Mode=OneTime}"
                            VerticalTextAlignment="Center" />
                        <Label
                            Grid.Column="1"
                            FontAttributes="Bold"
                            Text="{Binding Property2, Mode=OneTime}"
                            VerticalTextAlignment="Center" />
                        <Label
                            Grid.Column="2"
                            FontAttributes="Bold"
                            Text="{Binding property3, Mode=OneTime}"
                            VerticalTextAlignment="Center" />
                        <Label
                            Grid.Column="3"
                            Text="{Binding Property4, Mode=OneTime}"
                            VerticalTextAlignment="Center" />
                    </Grid>
                </Border>

            </ViewCell>

        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Here is a screenshot of heap analysis number 1 image

Number two: image

I added the OneTime binding mode and the Border wrapping as a result of some googling that I have done (hours worth, btw), and they have helped, but not completely eliminated the problem. Are there good ways of debugging where these issues are coming from?

Could someone help me understand why this is happening? I am a total newbie to memory leak issues, and I'm not sure where my issues begin and MAUI's end. This is our first hop into MAUI as a company and there is a lot riding on this.

Steps to Reproduce

N/A

Link to public reproduction project repository

No response

Version with bug

8.0.40 SR5

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

Windows Build 22631.3737

Did you find any workaround?

Not yet.

Relevant log output

No response

github-actions[bot] commented 3 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

ajsuydam commented 3 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

* [Memory Leak with CollectionView (#14993)](https://github.com/dotnet/maui/issues/14993),  similarity score: 0.80

* [Memory leak reloading list items on Windows (#18030)](https://github.com/dotnet/maui/issues/18030),  similarity score: 0.80

Closed similar issues:

* [Memory leaks EVERYWHERE (#12039)](https://github.com/dotnet/maui/issues/12039),  similarity score: 0.82

* [Massive memory leak in CollectionView while scrolling (#10560)](https://github.com/dotnet/maui/issues/10560),  similarity score: 0.81

* [ListView/CollectionView memory leak under Windows (#9162)](https://github.com/dotnet/maui/issues/9162),  similarity score: 0.81

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

While all of those are similar, unfortunately they do not cover my specific issue. They were good reads though and help me not feel so bad that I'm causing gigs of memory to leak. Seems like there's a lot of work to do.

In the mean time, another question is if there are any good alternatives to ListView. That is a potential work around.

PureWeen commented 3 months ago

@ajsuydam Have you tried CollectionView?

ajsuydam commented 3 months ago

@PureWeen so that's weird, I just tried it, and the exact same code (just switching out ListView for Collection View) gives me a null reference exception. It's supposed to be a drop-in replacement right?

Scratch that. I figured that out.

ajsuydam commented 3 months ago

@PureWeen Ok can confirm the issue is not present with the CollectionView. Not sure why that is though....

jonathanpeppers commented 3 months ago

@ajsuydam do you see the same issue in a sample app with a ListView? Can you share a sample project?

In the nightly build, we should have fixed a problem for ListView on iOS, but not Windows:

ajsuydam commented 3 months ago

@ajsuydam do you see the same issue in a sample app with a ListView? Can you share a sample project?

In the nightly build, we should have fixed a problem for ListView on iOS, but not Windows:

* [[ios] fix leak in ListView *Cells #23143](https://github.com/dotnet/maui/pull/23143)

@jonathanpeppers I'll see if I have some spare time next week to come up with something, but it will be difficult, timeline here is pretty tight.

On a related note, are there any good resources you'd recommend for getting started with improving the memory performance of my app? I have tons of data to display, and the number of binding references looks set to increase exponentially. Need to figure out a way to analyze these heap snapshot reports, and then take action on them.

ajsuydam commented 3 months ago

Also just want to say thanks to both of you @jonathanpeppers @PureWeen for your quick responses on this. Confidence boost for sure.

LeonSweden commented 3 months ago

I did experience the very same where I had a ListView in a VerticalStackLayout. The solution was a simple as change encapsulate of my ListView to be in a StackLayout.

The ListView has 1000+ elements and it loads fast w/o memory leaks. I've organized it in a TabbedPage where it started to leak memory after I switched tab from my list to something else and then back again. After changing to StackLayout, I've no memory leaks.

MartyIX commented 2 months ago

On a related note, are there any good resources you'd recommend for getting started with improving the memory performance of my app?

https://learn.microsoft.com/en-us/dotnet/maui/deployment/performance?view=net-maui-8.0 is the best I know of

ajsuydam commented 2 months ago

On a related note, are there any good resources you'd recommend for getting started with improving the memory performance of my app?

https://learn.microsoft.com/en-us/dotnet/maui/deployment/performance?view=net-maui-8.0 is the best I know of

@MartyIX Thanks, I have referenced that already a bunch. I think maybe a better question that I should have asked is are there any good resources for how to use the .net memory analyzers and how to find the patterns in my programming that are resulting in the objects being kept alive.

ajsuydam commented 2 months ago

@jonathanpeppers @PureWeen For now I'm going to mark this as closed since the immediate issue has been resolved. But I would appreciate any resources y'all have!

MartyIX commented 2 months ago

I think maybe a better question that I should have asked is are there any good resources for how to use the .net memory analyzers and how to find the patterns in my programming that are resulting in the objects being kept alive.

I would check fixes of memory leaks https://github.com/dotnet/maui/pulls?q=is%3Apr+label%3A%22memory-leak+%F0%9F%92%A6%22+is%3Aclosed In a way, it documents how memory leaks are diagnosed and then unit tested to prevent them from appearing again.

There is also https://github.com/dotnet/maui/wiki/Memory-Leaks (it should be up to date or mostly up to date AFAIK).

Other than that I'm not aware of any other sources.