microsoft / XamlBehaviors

This is the official home for UWP XAML Behaviors on GitHub.
MIT License
697 stars 112 forks source link

Interactivity.BehaviourCollection previous page values when navigaion to new page #186

Closed abk90007 closed 3 years ago

abk90007 commented 4 years ago

Hi,

I am facing a memory leak issue with interactivity behaviour collection. It is not able to clear previous page records(objects) from the collection if user is navigating to new page. This will result in increase in app memory every time user navigates to new page.

Is there any way of clear those objects?

Regards, Abhishek

pedrolamas commented 4 years ago

Can you please provide a sample app for the problem you are seeing?

abk90007 commented 4 years ago

Here is the image of behaviour collection of the profiler. Is this helpful? Will share a sample app soon. img1

abk90007 commented 4 years ago

@PedroLamas PFA sample for this issue. App4.zip

pedrolamas commented 4 years ago

I ran your sample app through the profiler with "Memory Usage" enabled, took a snaphot when it started, navigated to a couple of pages, took another snapshot, and finally clicked the GC button and took a final snapshot.

In the end, I got a single instance of the BehaviorsCollection which is what I expected, so I'm not sure if I'm missing somethin here, but seems the class is getting correctly GC'ed when it is not needed anymore.

abk90007 commented 4 years ago

@PedroLamas BehaviorsCollection has a single instance, but it contains all the behaviors of the current page and previous pages. You can see the behaviors collection counter increasing by 3 when navigating to new page in the snapshots. Previous page objects are not clearing from the collection when navigating to a new page. Are we have to dispose these objects manually? If yes, then how?

pedrolamas commented 4 years ago

Pretty much the same result... I see the number rising, but it goes down as expected when I force GC.

image

Open the app, take snapshot:

image

Click a couple of times on navigation buttons, take snapshot:

image

Force GC, take snapshot:

image

Are we have to dispose these objects manually? If yes, then how?

No, it should be automatically GC'ed when they are not in use!

pbdev972 commented 4 years ago

@PedroLamas , I am facing same issue but unable to figure out why these interactivity instances are not getting dispose, Can you please check once , why these instances are not getting dispose?

pedrolamas commented 4 years ago

@pbdev972 This is quite hard to help without knowing your specific scenario. Ideally, I would ask that you provide a sample app that shows the problem you are having so we can debug and try to understand what is the problem.

pbdev972 commented 4 years ago

@PedroLamas , you can use same sample app attached above and can check scenario -navigating to next page and can verify why these interactivity instances are still there or getting increase for multiple navigation , please let me know what else I can provide to debug this ? basically my previous viewmodel instances are not getting dispose on navigation as they are having dependency on interactivity instance :(

pedrolamas commented 4 years ago

First of all, the sample app above is using Microsoft.Xaml.Behaviors.Uwp.Managed version 2.0.0, please make sure to use the latest 2.0.1 as this contains some bug fixes.

I took the app and added some debug code to it so I could monitor the classes being created and destroyed, something like this:

public sealed partial class MainPage : Page
{
    private static int InstanceCount = 0;
    private int currentInstance = 0;

    public MainPage()
    {
        currentInstance = System.Threading.Interlocked.Increment(ref InstanceCount);

        Debug.WriteLine($" ++ created MainPage {currentInstance}");

        this.InitializeComponent();
    }

    ~MainPage()
    {
        Debug.WriteLine($" -- destroyed MainPage {currentInstance}");
    }
}

I used this same approach for MainPage, SecondPage, MainPageViewModel and SecondPageViewModel

Then I added a new button on both pages that when clicked, runs the following code:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Debug.WriteLine(" ** GC.Collect");

    GC.Collect();
}

Run the app, output:

 ++ created MainPage 1
 ++ created MainPageViewModel 1

Click "Next Page", output:

 ++ created SecondPage 1
 ++ created SecondPageViewModel 1

Click "Next Page", output:

 ++ created MainPage 2
 ++ created MainPageViewModel 2

Click "GC", output:

 ** GC.Collect
 -- destroyed SecondPage 1
 -- destroyed MainPage 1

Click "GC" again, output:

 ** GC.Collect
 -- destroyed MainPageViewModel 1
 -- destroyed SecondPageViewModel 1

So what I see here is that the first GC collected the pages, and the second collected the view models.

It's normal that things don't get all GC'ed on first run, but in the end, everything was correctly collected and there was no memory leak!

pedrolamas commented 4 years ago

From my tests with the demo app, it doesn't seem to be any memory leak.

If no further information is provided soon, I will consider this issue settled and close it.