-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Memory Leak issue in ListView #16450
Comments
(@jonathanpeppers works on #16346 (iOS memory leaks). CheckBox is mentioned there as well. Not sure if by any chance a fix there can fix it for Windows as well.) |
@Tamilarasan-Paranthaman does this problem happen on .NET 8? The test I added for There are various other fixes that are not in .NET 7. |
@jonathanpeppers I have tested the provided sample with ".NET 8" on the "Windows" platform and encountered the same issue. |
So, it looks like even if you have an empty Notice the overall heap size at the end got up to 3,964 kb. I looked here: The problem is every maui/src/Controls/src/Core/Cells/Cell.cs Lines 197 to 201 in 9fcccd5
And so the one Now I do think everything would go away if you navigated away from this page. Or a workaround would be to create two |
I can reproduce it in a test here: main...jonathanpeppers:ListViewOhNo This line appears to also be problematic, commented out along with maui/src/Controls/src/Core/Element/Element.cs Line 322 in 9fcccd5
|
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process. |
Verified this on Visual Studio Enterprise 17.8.0 Preview 1.0. Repro on Windows 11 .NET 8 with below Project: |
I added some logging to track each data-bound item: List<WeakReference> references = new();
public MainPage()
{
InitializeComponent();
listView.ItemTemplate = new DataTemplate(() =>
{
var cell = new ViewCell();
references.Add(new(cell));
return cell;
});
}
void Log()
{
Debug.WriteLine($"Cells alive: {references.Count(l => l.IsAlive)}");
} It looks like this issue only happens with
Where if I change to a
So, a second workaround is to use |
Context: https://github.com/Tamilarasan-Paranthaman/Maui-Itemssource-Switching-Issue Fixes: dotnet#16450 In a customer sample, swapping a `ListView.ItemsSource` back and forth, such as: listView.ItemsSource = employeeInfoRepository.EmployeesInfo1; listView.ItemsSource = employeeInfoRepository.EmployeesInfo2; Appears to create new `Cell`'s for each call -- and each new cell lives forever. I could reproduce this issue in a device test. Viewing a memory snapshot, each `Cell` via `Cell.Parent` subscribes to events on their parent, the `ListView`: * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Cells/Cell.cs#L197-L201 * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Element/Element.cs#L322 This makes the `ListView` hold onto each `Cell` causing them to live forever. However, the leak would go away if you navigated away from the current `Page`, removed the `ListView` from the screen, etc. Possible workarounds were: 1. Use two `ListView` instead, and show/hide them. 2. Use a `CollectionView` instead. The fix I came up with appears to be reasonable. In `CellControl.OnUnloaded`: void OnUnloaded(object sender, RoutedEventArgs e) { // ... // 🚀 unsubscribe from propertychanged Cell.PropertyChanged -= _propertyChangedHandler; // Allows the Cell to unsubscribe from Parent.PropertyChanged Cell.Parent = null; } This event is fired when WinUI has removed the `CellControl` from the visual tree. We can safely *unset* the `Cell`'s `Parent`, which unsubscribes from the problematic events. If the `Cell` is later re-added to the visual tree, it's `DataContext` will be updated. In `CellControl`'s `SetCell(object newContext)` the `Cell.Parent` is reset to the `ListView`. I added two test cases for this scenario: one for the leak, and one to prove that re-setting `ItemsSource` still works.
I have checked the same test case using the <?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"
xmlns:local="clr-namespace:MauiApp1"
x:Class="MauiApp1.MainPage">
<ContentPage.BindingContext>
<local:EmployeeInfoRepository x:Name="employeeInfoRepository"/>
</ContentPage.BindingContext>
<Grid RowDefinitions="Auto,*">
<HorizontalStackLayout Grid.Row="0">
<Button Text="ItemSource 1" Clicked="ItemSource_One_Button_Clicked"/>
<Button Text="ItemSource 2" Clicked="ItemSource_Two_Button_Clicked"/>
</HorizontalStackLayout>
<CollectionView Grid.Row="1" x:Name="listView" ItemsSource="{Binding EmployeesInfo1}">
<CollectionView.ItemTemplate>
<DataTemplate>
<CheckBox x:Name="checkBoxCell" Margin="10,0,0,0" IsChecked="{Binding IsChecked}"
VerticalOptions="Center">
</CheckBox>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
When I replaced the CheckBox with a label in the DataTemplate, the crash did not occur, and the application size did not increase significantly. It seems that the presence of a MAUI_checkbox.mp4 |
Let me fix the underlying issue with all The control itself doesn't leak in isolation, as we have a test for it: maui/src/Controls/tests/DeviceTests/Memory/MemoryTests.cs Lines 36 to 51 in 0ebb60b
|
So, I'm testing a local build from PR #16762 (basically .NET 8).
My changes to the app are here: jonathanpeppers/Maui-Itemssource-Switching-Issue@43af9ec |
* [windows] fix memory leak in ListView Context: https://github.com/Tamilarasan-Paranthaman/Maui-Itemssource-Switching-Issue Fixes: #16450 In a customer sample, swapping a `ListView.ItemsSource` back and forth, such as: listView.ItemsSource = employeeInfoRepository.EmployeesInfo1; listView.ItemsSource = employeeInfoRepository.EmployeesInfo2; Appears to create new `Cell`'s for each call -- and each new cell lives forever. I could reproduce this issue in a device test. Viewing a memory snapshot, each `Cell` via `Cell.Parent` subscribes to events on their parent, the `ListView`: * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Cells/Cell.cs#L197-L201 * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Element/Element.cs#L322 This makes the `ListView` hold onto each `Cell` causing them to live forever. However, the leak would go away if you navigated away from the current `Page`, removed the `ListView` from the screen, etc. Possible workarounds were: 1. Use two `ListView` instead, and show/hide them. 2. Use a `CollectionView` instead. The fix I came up with appears to be reasonable. In `CellControl.OnUnloaded`: void OnUnloaded(object sender, RoutedEventArgs e) { // ... // 🚀 unsubscribe from propertychanged Cell.PropertyChanged -= _propertyChangedHandler; // Allows the Cell to unsubscribe from Parent.PropertyChanged Cell.Parent = null; } This event is fired when WinUI has removed the `CellControl` from the visual tree. We can safely *unset* the `Cell`'s `Parent`, which unsubscribes from the problematic events. If the `Cell` is later re-added to the visual tree, it's `DataContext` will be updated. In `CellControl`'s `SetCell(object newContext)` the `Cell.Parent` is reset to the `ListView`. I added two test cases for this scenario: one for the leak, and one to prove that re-setting `ItemsSource` still works. * Update ListViewTests.cs
* [windows] fix memory leak in ListView Context: https://github.com/Tamilarasan-Paranthaman/Maui-Itemssource-Switching-Issue Fixes: #16450 In a customer sample, swapping a `ListView.ItemsSource` back and forth, such as: listView.ItemsSource = employeeInfoRepository.EmployeesInfo1; listView.ItemsSource = employeeInfoRepository.EmployeesInfo2; Appears to create new `Cell`'s for each call -- and each new cell lives forever. I could reproduce this issue in a device test. Viewing a memory snapshot, each `Cell` via `Cell.Parent` subscribes to events on their parent, the `ListView`: * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Cells/Cell.cs#L197-L201 * https://github.com/dotnet/maui/blob/9fcccd57b5a3d664e4788b3c7fc3edc10010beaf/src/Controls/src/Core/Element/Element.cs#L322 This makes the `ListView` hold onto each `Cell` causing them to live forever. However, the leak would go away if you navigated away from the current `Page`, removed the `ListView` from the screen, etc. Possible workarounds were: 1. Use two `ListView` instead, and show/hide them. 2. Use a `CollectionView` instead. The fix I came up with appears to be reasonable. In `CellControl.OnUnloaded`: void OnUnloaded(object sender, RoutedEventArgs e) { // ... // 🚀 unsubscribe from propertychanged Cell.PropertyChanged -= _propertyChangedHandler; // Allows the Cell to unsubscribe from Parent.PropertyChanged Cell.Parent = null; } This event is fired when WinUI has removed the `CellControl` from the visual tree. We can safely *unset* the `Cell`'s `Parent`, which unsubscribes from the problematic events. If the `Cell` is later re-added to the visual tree, it's `DataContext` will be updated. In `CellControl`'s `SetCell(object newContext)` the `Cell.Parent` is reset to the `ListView`. I added two test cases for this scenario: one for the leak, and one to prove that re-setting `ItemsSource` still works. * Update ListViewTests.cs
@MartyIX @jonathanpeppers @PureWeen @jsuarezruiz @samhouts |
It should be in https://github.com/dotnet/maui/releases/tag/8.0.0-rc.1.9171. It mentions:
(But literaly above your post one can see |
Is it available in VS preview#17.8.0-pre.1.0 |
I am still encountering the same issue in version Recording.mp4Sample Link: Application.zip Additionally, while reviewing your application, I noticed that you added a Label without assigning any text within the ViewCell, instead of using a CheckBox. Is there a specific reason for this choice? |
#16762 fixed a general problem with all I will retest your app above, thanks. |
@Tamilarasan-Paranthaman in your video is XAML hot reload disabled? (I see the toolbar in your video, so I guess it might not be?) XAML hot reload is known to cause diagnostic/profiling tools to show incorrect results, they display a warning on this screen: This is mentioned here: |
@jonathanpeppers, the XAML hot reload is not disabled in my Visual Studio. However, I'm still facing the same issue even after disabling it. |
@Tamilarasan-Paranthaman for testing this, do you also have some This is mentioned as a troubleshooting step that makes the GC at least slightly more deterministic: (remove these when your testing is done) I tested your app again on Friday with |
Hi @Tamilarasan-Paranthaman. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. 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. |
@jonathanpeppers, I have tested the application with GC.Collect() calls, and the However, why does the issue reproduce when binding the Checkbox in the XAML page? This issue occurred in both XAML hot reload enabled and disabled cases. There is an issue when binding the Checkbox on the XMAL page? |
So, you still see an issue? Or not? If you remove |
@jonathanpeppers, I'm still encountering the issue even after disabling XAML hot reload in my application, which leads to a crash. I have already attached my updated sample to this query #16450 (comment). As per your suggestion, I also test it by adding a checkbox along with GC.Collect() calls in the code-behind. In this scenario, the issue did not reproduce when XAML hot reload was disabled.
The difference between the two samples lies in the addition of a Checkbox, with one being added in XAML and the other in the code behind. Recording.mp4 |
Did you try this suggestion?
In the video why isn't there a To verify, you are using .NET 8 RC 1 and the project has |
I tested with the .NET 8 RC 2 release today, only change to your sample was added I don't feel like I'm seeing a leak at all, when taking a snapshot between each button press: @Tamilarasan-Paranthaman I would like to solve a memory issue here if there is one, but I'm not currently able to see it. If you can give more details or info, we can investigate further. Thanks! |
Description
I have a
CheckBox
in theListView
DataTemplate and am switching the ListView's ItemsSource at runtime. Due to this, the app size gradually increases and eventually leads to a crash of the application.checkbox.mp4
Steps to Reproduce
Link to public reproduction project repository
https://github.com/Tamilarasan-Paranthaman/Maui-Itemssource-Switching-Issue
Version with bug
7.0.86
Last version that worked well
Unknown/Other
Affected platforms
Windows, I was not able test on other platforms
Affected platform versions
Windows
Did you find any workaround?
No response
Relevant log output
No response
The text was updated successfully, but these errors were encountered: