Bug 59271 - Memory Leak when using x:Reference within the ItemTemplate in ListView
Summary: Memory Leak when using x:Reference within the ItemTemplate in ListView
Alias: None
Product: Forms
Classification: Xamarin
Component: Android ()
Version: 2.4.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2017-09-06 20:56 UTC by halilgoecer
Modified: 2017-09-11 19:40 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Test Project + Screenshot (435.98 KB, application/zip)
2017-09-06 20:56 UTC, halilgoecer

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description halilgoecer 2017-09-06 20:56:18 UTC
Created attachment 24609 [details]
Test Project + Screenshot

I'm using a list with more than 1000 items. The CachingStrategy is "RecycleElement". I have a custom ItemTemplate in which I have Bindings like 

BackgroundColor="{Binding BindingContext.BackgroundColor, Source={x:Reference RootPage}}

If I now scroll down the list in Android, the memory fills up with objects of type "System.Delegate", please look at the screenshot below. Because of this the scrolling gets laggy and the memory consumption rises continuously. If I change the ItemTemplate so that it doesn't use x:Reference this problem doesn't occur and I can scroll smoothly.

I added a test project in the attachment and you can test this yourself using the Xamarin Profiler.

Xamarin Profiler screenshot: https://imgur.com/a/mR8n7
Xamarin Profiler Trace (167MB): https://mega.nz/#!U0IkybTR!RWRinl50YPEfY1BoSaNB6UBvPE6Unl-56bFkGiESJXk

I tested this issue only in Android. Maybe iOS and UWP is also affected.
I'm hoping that you can fix this.

Full XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             x:Class="MemoryLeakTest.MainPage" x:Name="RootPage">

    <ListView x:Name="TestListView" CachingStrategy="RecycleElement"  VerticalOptions="Fill"  HorizontalOptions="Fill">
                            <RowDefinition Height="{Binding BindingContext.FirstRowHeight, Source={x:Reference RootPage}}"></RowDefinition>
                            <RowDefinition Height="{Binding BindingContext.SecondRowHeight, Source={x:Reference RootPage}}"></RowDefinition>
                        <Label Text="{Binding BindingContext.HeaderText, Source={x:Reference RootPage}}"  BackgroundColor="{Binding BindingContext.BackgroundColor, Source={x:Reference RootPage}}"></Label>
                        <Label Grid.Row="1" Text="{Binding Text}"  BackgroundColor="{Binding BindingContext.BackgroundColor, Source={x:Reference RootPage}}"></Label>

Comment 1 Jimmy [MSFT] 2017-09-11 19:29:57 UTC
Thank you for filing this report! I ran the attached project on a BLU R1 HD device and I don't believe this is a memory leak. 

I updated the project to Xamarin.Forms 2.4.0-pre2, available on NuGet as a pre-release, and used Xamarin Profiler. I created a snapshot after the app launched, every time I scrolled around 1000 items, and a couple of seconds after reaching the end of the list. The allocations list did indicate that there were 101,237 System.Delegate[] objects, however by default this list shows the _total_ allocations during the profiling session. 

After enabling "Only Live Objects" in the allocation info panel, it now showed that only 104 System.Delegate[] were actually still alive. And under the "Snapshots" tab you could see that the GC did clean up some objects while scrolling down the list. 

Profiler trace: https://www.dropbox.com/s/qyiiz2qyw0xmkju/2.4.0-all-bindings.mlpd?dl=0

Looking at the profiler trace you provided, there do not appear to be any snapshots created during the session therefore the "Only Live Objects" option is disabled. Running the profiler again with snapshots should result in much fewer System.Delegate[] objects being shown as still allocated.

Regarding the scrolling performance, I did not experience any significant difference between the ItemTemplate using and not using x:Reference. In both cases scrolling would lag for a moment if I tried to scroll very fast, but scrolling at a constant speed worked fine. I would suggest not using bindings for the RowDefinitions if they are always the same value as this will avoid the binding having to be calculated every time the ViewCell.BindingContext changes and could result in a slight performance gain. However I do admit though that there is still room for improvement which is why Android performance continues to be a focus for the team.

Hope this helps!
Comment 2 halilgoecer 2017-09-11 19:40:53 UTC
Thank you, this helps. Didn't know that the values in the profiler show the total allocations and not the live objects. Anyway I now use normal properties that get their value from a static class as bindings and have now much better scrolling performance.