Bug 41271 - [UWP] Memory Leak from ListView in TabbedPage
Summary: [UWP] Memory Leak from ListView in TabbedPage
Status: RESOLVED FIXED
Alias: None
Product: Forms
Classification: Xamarin
Component: Windows (show other bugs)
Version: 2.2.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2016-05-23 19:28 UTC by Michael
Modified: 2016-11-09 21:54 UTC (History)
6 users (show)

See Also:
Tags: ac
Is this bug a regression?: ---
Last known good build:


Attachments
repo case (296.73 KB, application/zip)
2016-05-23 19:28 UTC, Michael
Details

Description Michael 2016-05-23 19:28:20 UTC
Created attachment 16079 [details]
repo case

Description:
Xamarin.Forms UWP project leaks memory when navigating between Tabs of a TabbedPage that is nested in a NavigationPage and housed in the Detail of a MasterDetailPage. Each Page in the TabbedPage Children is a simple ContentPage with a Listview. As you switch between tabs, you can see the memory heap grow and the object count grow very very quickly. 

Steps to reproduce:
1. Run attached repo project
2. Take Heap Snapshot once app has fully loaded and memory tops off
3. Switch between a few tabs in the TabbedPage
4. Take a Heap snapshot to compare and notice the increase in objects/Heap

Expected Results:
Memory from previous tabs is released and application memory should stabilize at some point.

Observed Results:
Each tab viewed adds more memory to the overall heap size and memory is never released. 

System Info:
Visual Studio Enterprise 2015 Version 14.0.25123 Update 2
Microsoft .NET Framework Version 4.6.01038
Xamarin 4.0.3.214
Comment 1 Samantha Houts [MSFT] 2016-05-23 21:45:59 UTC
If you add a fixed RowHeight to your ListView, you'll trigger virtualization, which will prevent the enormous heap size. The memory will still increase as you switch between tabs, but it will not continue to increase once the first page of every tab has been loaded. Does this resolve your issue?

Thank you!
Comment 2 Michael 2016-05-31 22:32:15 UTC
I have verified that setting a fixed RowHeight in the ListView does prevent the memory leak. This workaround resolved the issue.
Comment 3 Samantha Houts [MSFT] 2016-06-01 21:17:23 UTC
Great! I'm confirming this bug for further investigation, as it does seem that the ListView should be released on tab change.
Comment 4 Samantha Houts [MSFT] 2016-06-01 21:17:51 UTC
changing status
Comment 5 Jeff Dalby 2016-07-30 19:52:14 UTC
I'm running into this as well, currently running 2.3.1.113-pre3. Difference is I'm not using a tabbed layout I'm using Prism, and opening the page via a home page using modal navigation, and then returning to a homepage using GoBack, which is just PopModalAsync.  In this scenario the fixed height isn't solving the problem since the page is recreated each time you navigate to it.  It seems the ListView issue prevents the previous page from ever being garbage collected (finalizer is never called), and since it's a complex dashboard, that's a pretty bad thing.  Based on this description it seems it would have the same root cause.  Attempts to manually clean things up setting the listview to null in a dispose method, or in OnDisappearing don't help seem to help.  Doesn't take much to break a page just add :

<ListView x:Name="MyTest" ItemsSource="{Binding MyTestEntries}" SeparatorVisibility="None" VerticalOptions="StartAndExpand">
                <ListView.ItemTemplate>
                  <DataTemplate>
                    <ViewCell>
                      <ContentView HeightRequest="250"/>
                    </ViewCell>
                  </DataTemplate>
                </ListView.ItemTemplate>

              </ListView>

You can also set the ViewCell height, or the RowHeight.  If you remove the the ContentView from the ViewCell in the example above so it's blank (and now useless) while making sure not to have a RowHeight or ViewCell Height set it will allow the page to be GC'd.
Comment 6 Jeff Dalby 2016-07-30 19:56:13 UTC
I should add that this is a show stopper for us releasing a UWP app, since if you navigate back and forth enough times you'll run the machine/phone out of memory.
Comment 7 Samantha Houts [MSFT] 2016-09-20 00:51:01 UTC
Upon further investigation, the caching of tab pages described here appears to be an expected UWP behavior. I recommend setting the ItemSource of the ListView to null OnDisppearing. This clears the created Cells from the VisualTree. See https://github.com/xamarin/Xamarin.Forms/pull/367/files for an example.

@Jeff Dalby, if this latest workaround does not help with your situation, would you be able to attach a sample reproduction that demonstrates the problem?
Comment 8 Rui Marinho 2016-09-27 13:47:30 UTC
Should be fixed in 2.3.4-pre1
Comment 9 Mike 2016-11-09 21:33:51 UTC
@Michael, Did you sure that's a TabbedPage problem?  I worry that any page switch between exists page will cause this problem.  Like:

App.MainPage = exists page;
MasterDetail.Details = exists page;
Navigation.Push or pop to exists page
Comment 10 Mike 2016-11-09 21:54:23 UTC
@Samantha Houts, I tried what you recommend, but not working...

   private MyViewModel temp;
        protected override void OnAppearing()
 	{
 		base.OnAppearing();

                if (null != temp)
                    lvProductList.ItemsSource = temp.ProductList;


        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();

            temp = (this.BindingContext as MyViewModel);
            lvProductList.ItemsSource = null;
        } 

Also please see: https://bugzilla.xamarin.com/show_bug.cgi?id=45722

Note You need to log in before you can comment on or make changes to this bug.