I've been spending a lot of time trying to track down memory leaks in our Xamarin.Forms app on Android. After a lot of blind alleys and false dawns, I think I may have come across something which is causing the problem.
Using Xamarin Profiler, I can see that as soon as I create a Style and apply it to a control (or in fact just an implicit style), we get Multiple WeakReferences remaining 'Live' - i.e. not garbage collected.
Note that I assume that the objects to which they refer have been GC'd (because the reference to the object is weak), but the WeakReferences themselves are remaining.
Now of course WeakReferences are small I know - but when you have hundreds created on every iteration of a page push/pop, then the memory adds up and we have a significant leak.
Here are the details.
Using Xamarin.Forms 2.3.4.270 (we haven't upgraded because we want to keep with known issues!)
Running on Android - physical device.
App.xaml:
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:ProfiledFormsApp2;assembly=ProfiledFormsApp2"
x:Class="ProfiledFormsApp2.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Page XAML:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage Title="Plain Page" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ProfiledFormsApp2.PlainPage">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Core Navigation"/>
<Label Text="Number of items:" />
<Label Text="{Binding ItemsCount}" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
When I navigate to the above page and back 3 times, we have the following WeakReference (and related) classes created - the screenshot below is from a Profiler snapshot.
Note we have 55 WeakReferences. Drilling into these shows:
What is interesting is that these WeakReferences seem to be created as part of Behavior and Trigger attaching. Looking at the call tree for the top one gives:
So it appears that the WeakReference was created as part of setting a BindableObject's value and the subsequent setting of the Style.
And it also appears that the WeakReference is still in memory and being referenced by something - the Behavior collection?
Using Profiler, I'm can see that we don't have Labels remaining un GC'd. It seems to be something in the Theme/Behavior/Trigger processing.
I haven't looked at the Xamarin.Forms code on GitHub yet - that might have to be my next action.
Has anyone observed this or got a solution?
@NMackay, @JohnHardman You may be interested in this as this could be the underlying cause of the memory leak I thought I observed some time ago and mentioned in a post here.