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
21.98k stars 1.71k forks source link

Memory leaks EVERYWHERE #12039

Closed Vroomer closed 1 year ago

Vroomer commented 1 year ago

Description

I'm trying to develop LoB app in MAUI, including lot's of CollectionViews and complex master-details with multiple views, data forms and custom controls. It's bumpy road, but by far the most critical issue for me is the amount of memory leaks, which makes the app completely unusable.

742nlk

I have already reported 2 issues resulting in severe memory leak and there have been many more raised over time by others. Unfortunately they aren't getting attention they deserve in my opinion.

The more I look into this topic, the more puzzled I'm by memory management in MAUI and the more I'm determined that there is something horribly wrong happening inside MAUI. I decided to create another sample to demonstrate this issue and it's significance for production apps. The sample is very simple MVVM app with CollectionView of Items. Clicking on an item will bring you to a detail page.

This bit in DetailPage constructor was added to increase memory allocation of the detail to make the memory leak more obvious (Array.Clear(Bytes) causes array to be iterated and allocated):

        Bytes = new byte[1024 * 400000];
        Array.Clear(Bytes); 

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising from 100 MBs to several GBs very quickly. I added button to execute GC.Collect(), but forcing GC never disposes all the resources. image

Calling this to manually free some resources doesn't seem to have any effect.

        vm.Bytes = null;
        vm.Item = null;
        BindingContext = null;

I made several observations:

image

The issue is obvious in other samples as well, for example Monkey app by @jamesmontemagno https://github.com/dotnet-presentations/dotnet-maui-workshop

Note that there is no use of static resources or event subscription anywhere in the sample code.

I observed the issue only in Windows as I have no sufficient way to check memory in other platforms.

Any tips about how to dispose DetailPage with all the related resources would be very welcomed.

Steps to Reproduce

  1. Load the repository and run the app.
  2. Repeatedly open details from CollectionView by selecting them and then pop the DetailPage using the button while observing memory usage in ResMon/memory profiler.
  3. Click on the "Force GC" button to trigger GC - some memory resources might be disposed, but the memory leak persists.

Link to public reproduction project repository

https://github.com/Vroomer/MAUI-master-detail-memory-leak.git

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

Windows, I was not able test on other platforms

Affected platform versions

Windows SDK 10.0.22000

Did you find any workaround?

No response

Relevant log output

No response

8m0 commented 1 year ago

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising

Hi, the problem exists since Xamarin. And you can find similar bug reports for MAUI. I think this problem will be moved to "Backlog milestone" as always.

I remember that result can differ from debug and release. So you can test it on release version just to be sure.

angelru commented 1 year ago

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising

Hi, the problem exists since Xamarin. And you can find similar bug reports for MAUI. I think this problem will me moved to "Backlog milestone" as always.

I remember that result can differ from debug and release. So you can test it on release version just to be sure.

Between the memory leaks and the inefficiency of the CollectionView and other controls, and the Shell having minor bugs, how can we trust MAUI?

8m0 commented 1 year ago

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising

Hi, the problem exists since Xamarin. And you can find similar bug reports for MAUI. I think this problem will me moved to "Backlog milestone" as always. I remember that result can differ from debug and release. So you can test it on release version just to be sure.

Between the memory leaks and the inefficiency of the CollectionView and other controls, and the Shell having minor bugs, how can we trust MAUI?

I don't know what to say. I am considering to look into other frameworks for app development. As i see, somehow, they don't prioritize real problems or just leave it without any word.

wubalubadubdub55 commented 1 year ago

I have the same problem. cc: @PureWeen

mohachouch commented 1 year ago

@jsuarezruiz @PureWeen @jamesmontemagno @maddymontaquila @davidortinau same problem on Xamarin Forms

We spent 3 weeks, 2 developers trying to figure out why the pages are not cleaning up. Unable to find. We just see in the Xamarin Profiler that the Resource Dictionary memory increases

ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

mohachouch commented 1 year ago

Any update for this blocking bug @samhouts @jsuarezruiz

PureWeen commented 1 year ago

related https://github.com/dotnet/maui/issues/12344

nk54 commented 1 year ago

From @8m0

I think this problem will be moved to "Backlog milestone" as always.

This one made me laugh more than expected after I saw the bot moving this thread to the backlog milestone

I din't expect Xamarin to be memory leak proof because it wasn't a tech from Microsoft at first. But I expected MAUI to be better. Far better than its current state about momery leaks...

rkebelj commented 1 year ago

This is so sad.

nikolaykusch commented 1 year ago

Same problem. I have only one question. How to work with MAUI with such bugs?

symbiogenesis commented 1 year ago

There isn't an excuse for memory leaks on the platform, but the patterns that are likely to cause memory leaks are likely not great patterns for normal workloads. You shouldn't be abusing query parameters, for instance. And the leaks aren't any worse than Xamarin.Forms was. In my case, XF was worse. Until the platform bugs are fixed, the best you can do is focus on your own code.

Events are one of the most likely causes of leaks, and those can be solved if you implement WeakEventManager. That one is pretty easy to do.

I had seen worse leaks from the handlers in XF, particularly inside of CollectionViews. You could scroll and just watch the memory usage rise and rise endlessly. I think a lot of those issues were solved with MAUI. I don't see this at all with my app.

Premature optimization is a bad idea. Unless your app has a known memory issue, there is no reason to assume that it does. For me, converting from XF to MAUI caused a measurable and dramatic decrease in memory usage.

nikolaykusch commented 1 year ago

There isn't an excuse for memory leaks on the platform, but the patterns that are likely to cause memory leaks are likely not great patterns for normal workloads. You shouldn't be abusing query parameters, for instance. And the leaks aren't any worse than Xamarin.Forms was. In my case, XF was worse. Until the platform bugs are fixed, the best you can do is focus on your own code.

Events are one of the most likely causes of leaks, and those can be solved if you implement WeakEventManager. That one is pretty easy to do.

I had seen worse leaks from the handlers in XF, particularly inside of CollectionViews. You could scroll and just watch the memory usage rise and rise endlessly. I think a lot of those issues were solved with MAUI. I don't see this at all with my app.

Premature optimization is a bad idea. Unless your app has a known memory issue, there is no reason to assume that it does. For me, converting from XF to MAUI caused a measurable and dramatic decrease in memory usage.

In my case, this is the biggest problem with CollectionView. So much so that I'm currently trying to migrate to Uno

angelru commented 1 year ago

No hay excusa para las fugas de memoria en la plataforma, pero los patrones que probablemente causen fugas de memoria probablemente no sean buenos patrones para las cargas de trabajo normales. No debería abusar de los parámetros de consulta, por ejemplo. Y las filtraciones no son peores que las de Xamarin.Forms. En mi caso, XF fue peor. Hasta que se corrijan los errores de la plataforma, lo mejor que puede hacer es concentrarse en su propio código. Los eventos son una de las causas más probables de fugas y se pueden resolver si implementa WeakEventManager. Ese es bastante fácil de hacer. Había visto filtraciones peores de los controladores en XF, particularmente dentro de CollectionViews. Puede desplazarse y simplemente ver cómo el uso de la memoria aumenta y aumenta sin cesar. Creo que muchos de esos problemas se resolvieron con MAUI. No veo esto en absoluto con mi aplicación. La optimización prematura es una mala idea. A menos que su aplicación tenga un problema de memoria conocido, no hay razón para suponer que lo tiene. Para mí, la conversión de XF a MAUI provocó una disminución medible y dramática en el uso de la memoria.

En mi caso, este es el mayor problema de CollectionView. Tanto es así que actualmente estoy tratando de migrar a Uno

Memory and performance issues, which are related, try my sample: https://github.com/dotnet/maui/issues/12130

Thinking of migrating to Flutter.

Vroomer commented 1 year ago

@symbiogenesis I have big app ready for production and I can't release it because it goes from 200 MB to 2000 MB in matter of a few minutes of using it. It's by far the biggest problem I encountered as there is no workaround. It's not data objects being stuck, it's all just UI bits being held by strong references from brushes, gesture handlers and god knows what else. The problem is really serious. No events or things like that are causing my memory leaks. I either make sure to detach events or make them as a weak reference.

symbiogenesis commented 1 year ago

I loaded up thousands of records into a CollectionView today, and noticed that the scrolling on WinUI was actually smooth. Android and iOS were bad.

Looks like the recent PRs https://github.com/dotnet/maui/pull/12627 and https://github.com/dotnet/maui/pull/12660 will be helping.

Some tricks to try now include:

These tricks are all used by @angelru already, but not everyone may be aware.

In addition to those tricks and the aforementioned WeakReferences for events, other things to try:

angelru commented 1 year ago

I loaded up thousands of records into a CollectionView today, and noticed that the scrolling on WinUI was actually smooth. Android and iOS were bad.

Looks like the recent PRs #12627 and #12660 will be helping.

Some tricks to try now include:

  • Set constant and explicit heights everywhere possible
  • Set ItemSizingStrategy to MeasureFirstItem if possible
  • Set CompressedLayout.IsHeadless to true where possible
  • Set the Binding mode to OneTime where possible

These tricks are all used by @angelru already, but not everyone may be aware.

In addition to those tricks and the aforementioned WeakReferences for events, other things to try:

  • Initialize collections early all at once, if possible, instead of adding a lot of records to the public property after it is created.
  • Cache complex objects and dynamic UI objects where possible, using something like a ConcurrentDictionary
  • Use the UniformItemsLayout from CommunityToolkit.Maui instead of anything fancier if everything is the same size.

Even if in my provided example you set: ItemSizingStrategy to MeasureFirstItem, activate AOT...

scrolling on Android/iOS is unacceptable. Try my sample.

akhanalcs commented 1 year ago

Any update on this serious bug?

symbiogenesis commented 1 year ago

Looks like this custom ListView control advertises that it avoids memory leaks

https://github.com/Keflon/FunctionZero.Maui.Controls

This one may also be useful, but only for Android and iOS:

https://github.com/roubachof/Sharpnado.CollectionView

this one also seems promising:

https://github.com/Redth/Maui.VirtualListView

nikolaykusch commented 1 year ago

I loaded up thousands of records into a CollectionView today, and noticed that the scrolling on WinUI was actually smooth. Android and iOS were bad.

Looks like the recent PRs #12627 and #12660 will be helping.

Some tricks to try now include:

  • Set constant and explicit heights everywhere possible
  • Set ItemSizingStrategy to MeasureFirstItem if possible
  • Set CompressedLayout.IsHeadless to true where possible
  • Set the Binding mode to OneTime where possible

These tricks are all used by @angelru already, but not everyone may be aware.

In addition to those tricks and the aforementioned WeakReferences for events, other things to try:

  • Initialize collections early all at once, if possible, instead of adding a lot of records to the public property after it is created.
  • Cache complex objects and dynamic UI objects where possible, using something like a ConcurrentDictionary
  • Use the UniformItemsLayout from CommunityToolkit.Maui instead of anything fancier if everything is the same size.

It won't help in my case. A lot of VM updates, binding - TwoWay

juwens commented 1 year ago

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising

Hi, the problem exists since Xamarin. And you can find similar bug reports for MAUI. I think this problem will be moved to "Backlog milestone" as always.

I remember that result can differ from debug and release. So you can test it on release version just to be sure.

That resembles exactly what I’ve seen in the Xamarin forms issue board.
I suspected that they carry over a lot of bugs, which „conveniently“ for them do not (yet) exist in Maui issue tracker.
Xamarin/Maui Team focuses on adding new features for shell, etc. these features are usually broken from the beginning. And they ignore severe existing issues. Only tiny bugs get fixed. And some bugfixes are so bad/lazy that you want to scratch your eyes out.

This will not change, until some MS Manager forces it‘s team to use Maui for a production app.

No official MS product uses Xamarin.Forms or Maui. Guess why. Cause they know how bad it is, and avoid it like the plague. And they know that there is no way to reason with the Xamarin/Maui team, about how far away they are from a production quality framework. Why Maui team has the perspective that they delivered the best thing ever, and many issue-tickets are an indicator of the good quality of Maui.

angelru commented 1 year ago

If you keep navigating back and forth from master to its details and watch memory usage, you will see memory raising

Hi, the problem exists since Xamarin. And you can find similar bug reports for MAUI. I think this problem will be moved to "Backlog milestone" as always. I remember that result can differ from debug and release. So you can test it on release version just to be sure.

That resembles exactly what I’ve seen in the Xamarin forms issue board. I suspected that they carry over a lot of bugs, which „conveniently“ for them do not (yet) exist in Maui issue tracker. Xamarin/Maui Team focuses on adding new features for shell, etc. these features are usually broken from the beginning. And they ignore severe existing issues. Only tiny bugs get fixed. And some bugfixes are so bad/lazy that you want to scratch your eyes out.

This will not change, until some MS Manager forces it‘s team to use Maui for a production app.

No official MS product uses Xamarin.Forms or Maui. Guess why. Cause they know how bad it is, and avoid it like the plague. And they know that there is no way to reason with the Xamarin/Maui team, about how far away they are from a production quality framework. Why Maui team has the perspective that they delivered the best thing ever, and many issue-tickets are an indicator of the good quality of Maui.

I am very frustrated with MAUI, I proposed it at the company I work for as a good framework for cross platform app development. But we find memory errors and disastrous performance in very important controls that prevent us from taking an application to production.

symbiogenesis commented 1 year ago

@angelru, I recommend swapping out your controls (particularly CollectionView) with those from Syncfusion, DevExpress, or one of the other providers, and seeing if that fixes it. The free demo versions of those controls should help you answer that question without committing to purchasing. Better than not shipping.

This post inspired me to try to fix up some open source CollectionView-based controls, like Maui.DataGrid, with about a dozen PRs, but after having done so, it is clear that if the record counts are very high then you will see noticeable leaks with the platform handlers almost regardless of what you do on your end.

The open source controls I linked to earlier will probably work for some use-cases, though. Might need to get your hands dirty with PRs.

symbiogenesis commented 1 year ago

Cool branch to check out, regarding caching item templates in the ColllectionView on Android.

https://github.com/dotnet/maui/commits/cv-recycle-templateselector-templates

nikolaykusch commented 1 year ago

@angelru, I recommend swapping out your controls (particularly CollectionView) with those from Syncfusion, DevExpress, or one of the other providers, and seeing if that fixes it. The free demo versions of those controls should help you answer that question without committing to purchasing. Better than not shipping.

This post inspired me to try to fix up some open source CollectionView-based controls, like Maui.DataGrid, with about a dozen PRs, but after having done so, it is clear that if the record counts are very high then you will see noticeable leaks with the platform handlers almost regardless of what you do on your end.

The open source controls I linked to earlier will probably work for some use-cases, though. Might need to get your hands dirty with PRs.

You were right. I replaced CollectionView with SfListView from Syncfusion and the problem is gone, no more memory leak when refreshing the VM and scrolling. Already got a Syncfusion community license, so now I can keep working

8m0 commented 1 year ago

Just wrote a comment about the problem under @jamesmontemagno latest video, the comment was deleted within 1 min.

symbiogenesis commented 1 year ago

Regarding WinUI, the latest service release updates to the WindowsAppsSDK 1.2.2. This SDK contains a fix for a memory leak in WinUI's ListView.

You can upgrade to it using:

dotnet workload update

1.2.3 of the WindowsAppsSDK is out, however, which fixes other bugs with that version. MAUI doesn't use it by default.

You can specify it with:

  <ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
    <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.230118.102" />
  </ItemGroup>

Looks like you might need to download the newer runtime on the client machine and reboot to get the latest WinUI runtime.

jamesmontemagno commented 1 year ago

Just wrote a comment about the problem under @jamesmontemagno latest video, the comment was deleted within 1 min.

I do not believe I deleted any of your comments, most likely auto moderated. I don't check comments that often.

8m0 commented 1 year ago

Just wrote a comment about the problem under @jamesmontemagno latest video, the comment was deleted within 1 min.

I do not believe I deleted any of your comments, most likely auto moderated. I don't check comments that often.

Hello, thanks for the answer. Could you do something regarding to the problem? It's very important problem which always got pushed to Backlog milestone.

akhanalcs commented 1 year ago

Little off topic but what does 'delighter' label mean? I ask that because @jsuarezruiz added this label to this issue 2 weeks ago.

jonathanpeppers commented 1 year ago

I tried this app: https://github.com/Vroomer/MAUI-master-detail-memory-leak.git

Using latest dotnet/maui/main. I changed one thing, just to try to make the GC button slightly better:

private async void Button_Clicked(object sender, EventArgs e)
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    await DisplayAlert("Done!", "Done!", "Ok");
}

Then I took an initial snapshot, and did CollectionView click, Pop page, Force GC getting a memory snapshot each time:

image

(notice the flat memory graph)

image

Initially, my thought that I would see new instances of these appearing (and that was the leak):

However, I don't see any of these objects being leaked.

To cross-verify this, I ran dotnet gcdump collect -p 29096:

https://devblogs.microsoft.com/dotnet/collecting-and-analyzing-memory-dumps/

Opening the dump, I see the expected bytes (and it does not grow as I navigate more):

image

image

I am not really seeing a problem currently with this sample & dotnet/maui/main.

Does anyone have a suggestion of something else I can try?

I will try the latest stable MAUI bits.

symbiogenesis commented 1 year ago

I am able to produce leaks on WinUI with the latest official .NET 7 servicing release. Haven't ever tried to test with main.

Just run the sample app, and scroll around and click the buttons on the top.

This branch is an example.

https://github.com/symbiogenesis/Maui.DataGrid/tree/memory-leak

image

symbiogenesis commented 1 year ago

Won't let me take a 4th snapshot. But rest assured it will be bigger.

image

jonathanpeppers commented 1 year ago

It seems like I found something.

Snapshot 2:

WeakReference<Microsoft.Maui.Controls.BindableObject>
Count: 1,545
Bytes: 37,080

Snapshot 10:

WeakReference<Microsoft.Maui.Controls.BindableObject>
Count: 1,657
Bytes: 39,768

I will keep investigating.

jonathanpeppers commented 1 year ago

I think this is on the right track: https://github.com/dotnet/maui/pull/13260

image

mohachouch commented 1 year ago

Hi @jonathanpeppers, Thanks for the fix of this bug. We have the same bug on Xamarin Forms. Can you do a PR also for Xamarin Forms. Thanks

mohachouch commented 1 year ago

As I said above. We have the same problem on Xamarin Forms on a large application. We have 15000 daily users for enterprise application. Xamarin Forms support is until May 2024. Please fix and don't forget Xamarin Forms users. @jonathanpeppers @jamesmontemagno @PureWeen @jsuarezruiz

hosamyousof commented 1 year ago

Hi @jamesmontemagno @PureWeen @jsuarezruiz @samhouts

Please, when we are going to have this update #13327 in .net 6 and .net 7??

jsuarezruiz commented 1 year ago

As I said above. We have the same problem on Xamarin Forms on a large application. We have 15000 daily users for enterprise application. Xamarin Forms support is until May 2024. Please fix and don't forget Xamarin Forms users. @jonathanpeppers @jamesmontemagno @PureWeen @jsuarezruiz

Will take a look to move the changes to Xamarin.Forms.

mohachouch commented 1 year ago

As I said above. We have the same problem on Xamarin Forms on a large application. We have 15000 daily users for enterprise application. Xamarin Forms support is until May 2024. Please fix and don't forget Xamarin Forms users. @jonathanpeppers @jamesmontemagno @PureWeen @jsuarezruiz

Will take a look to move the changes to Xamarin.Forms.

Thanks @jsuarezruiz

AlasaliCS commented 1 year ago

when will you update it for .net6 ? this is a serious and urgent problem need to be solved. thank you

jsuarezruiz commented 1 year ago

As I said above. We have the same problem on Xamarin Forms on a large application. We have 15000 daily users for enterprise application. Xamarin Forms support is until May 2024. Please fix and don't forget Xamarin Forms users. @jonathanpeppers @jamesmontemagno @PureWeen @jsuarezruiz

Will take a look to move the changes to Xamarin.Forms.

Changes already available in latest Xamarin.Forms SR.

ToolmakerSteve commented 1 year ago

"the amount of memory leaks, which makes the app completely unusable."

ghost commented 1 year ago

Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!