maui
maui copied to clipboard
Memory leaks on latest .NET 8 preview with Windows
Description
A data grid that I am working on leaks memory massively as you scroll around when there are a lot of records.
Steps to Reproduce
Just run the sample I provided, and start scrolling, etc.
Link to public reproduction project repository
https://github.com/symbiogenesis/Maui.DataGrid/tree/net8-memory-leak
Version with bug
8.0.0-preview.6.8686
Last version that worked well
Unknown/Other
Affected platforms
Windows
Affected platform versions
All
Did you find any workaround?
No.
Relevant log output
No response
@jonathanpeppers You may have some thoughts. Manually running GC doesn't help.
Everywhere you see +=
with an event
in this file is a potential leak:
https://github.com/symbiogenesis/Maui.DataGrid/blob/net8-memory-leak/Maui.DataGrid/DataGrid.xaml.cs
So far looking at this, I see several potential leaks in this DataGrid
control. It's probably not worth looking if there are further MAUI issues here without those solved.
Have you seen this wiki page? It might help you diagnose and track these down:
- https://github.com/dotnet/maui/wiki/Memory-Leaks
My code is already using the WeakEventManager for all of my events, and I unsubscribe to all of the events at what I think is the proper times, with the exception of a minor change I just made.
Not sure what else I ought to be doing. That link shows some similar event usage, and links to a PR that implements the WeakEventManager approach that I'm already using.
I think I see now. So the subscriptions to events that are located outside of MAUI in the .NET Framework are unsafe, and need a proxy wrapper to make them safe.
I will implement that and try again.
I just implemented that in the linked branch, except where WeakEventManager was being used, and the memory leaks remain
Especially on Windows, you should be able to see a tree of objects from a memory snapshot. What object is holding on to another object? If you can share their fully qualified name or the .gcdump
file that would make things clearer.
In addition to the Narrowing down the leak
instructions:
https://github.com/dotnet/maui/wiki/Memory-Leaks#narrowing-down-the-leak
Does the problem go away if you swap your custom DataGrid
control with something built-in? Like a ListView
or CollectionView
?
Can you address the XAML hot reload warning in your screenshot?
We mention it on the wiki page:
Did you also sprinkle some GC.Collect()
calls in the app as mentioned?
I had tried using GC.Collect() in the app before, to no effect. Just tried now, and there was no effect.
Just tried turning off XAML Hot Reload, and it had no effect.
Also removed the more complicated columns and just kept some simple text columns. And the leak remains.
Can you comment on:
Does the problem go away if you swap your custom DataGrid control with something built-in? Like a ListView or CollectionView?
Your latest screenshot shows the DataGrid
, but what is the exact object you think is leaking? So far, what I see are problems in this DataGrid
control.
The DataGrid control is mainly a wrapper for the CollectionView. Each row is a Grid, with identical ColumnDefinitions.
I personally think that the CollectionView is leaking.
Changing the CollectionView to a ListView does not resolve the problem.
Can you share a branch of your sample that uses ListView
or CollectionView
?
https://github.com/symbiogenesis/Maui.DataGrid/tree/net8-memory-leak
It isn't using the DataGrid
at all, correct?
I just updated this branch to just use a simple CollectionView, and the ListView version is commented out below it.
With this simple version, it also leaks, yes.
Specifically, I think it is only when using an ItemTemplate, and this issue has existed since Xamarin.Forms
I found this issue with ListView
: https://github.com/dotnet/maui/issues/16450#issuecomment-1670166956
But let me see if something similar is happening with CollectionView
as that seems more important. (It's the new control you're supposed to use)
This might have more to do with the Grid being inside of the ItemTemplate, rather than the ItemTemplate in general.
@symbiogenesis I did some debugging, and it appears the way the CollectionView
works.
- You have 150,000 rows, it apparently creates a
List<ItemTemplateContext>
with 150,000null
items... - This code is called as each row is scrolled into view:
https://github.com/dotnet/maui/blob/040f2f13c389a2092d03287bd794888704f33cae/src/Controls/src/Core/Platform/Windows/CollectionView/ItemTemplateContextList.cs#L25-L29
And so ItemTemplateContext
instances will grow as you scroll each one into view. I did not see the memory growing when I scroll to rows that were already on screen:
Now, I do see some things in the code here that could be improved -- but I'm not seeing a leak so far.
Do you feel like you are seeing something different than me? I will see if ListView feels any different.
One reason that I think it leaks is that navigating away from the page doesn't free up any memory. Even with a manual garbage collect.
I also tend to use more complicated DataTemplates, and with these scrolling back to rows that were already loaded does increase the memory usage.
navigating away from the page doesn't free up any memory I also tend to use more complicated DataTemplates
Can you update the sample to show this behavior? Or some examples of DataTemplate
that leak?
I tried ListView
, but it also seems OK when this change (merged today) is in place: 040f2f13c389a2092d03287bd794888704f33cae
I opened this one, as an obvious improvement looking at the existing code:
- https://github.com/dotnet/maui/pull/16838
I created a simple project, specified this XAML and using mouse scrolling up and down, you can increase memory consumption to over 3 gigabytes
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Sample.MultipleButtonsPage"
Title="test">
<StackLayout>
<CollectionView x:Name="collectionView"
ItemSizingStrategy="MeasureFirstItem"
VerticalOptions="FillAndExpand">
<CollectionView.ItemTemplate>
<DataTemplate>
<ContentView Padding="10">
<Label Text="{Binding .}"/>
</ContentView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
(ItemsSource is simple List
NET8, Controls nuget lib version 8.0.6
@scriptBoris I see the same thing as you. I just submitted PR https://github.com/dotnet/maui/pull/20036 that may help a bit with CollectionView on Windows. I'm sure there's lots more to do.
Verified this issue with Visual Studio Enterprise 17.10.0 Preview 1. Can repro on Windows platform with sample project. I disabled XAML Hot Reload, and after successful debugging, I scrolled up and down, but the problem still occurred.
https://github.com/symbiogenesis/Maui.DataGrid/tree/net8-memory-leak
Here is a sample where you can reproduce the issue. Run the application and click on the "Reload Data" button. On every data load, you will see that memory consumption is increasing. The sample contains a simple data template with a grid.