浏览页面时,所有UWP应用程序都会泄漏内存吗? [英] Do all UWP apps leak memory when navigating pages?

查看:60
本文介绍了浏览页面时,所有UWP应用程序都会泄漏内存吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我一直在努力尝试UWP,并在最新版本的Windows 10上使用VS2017 v15.6.4在C#中开发一个简单的应用程序.

So I've been getting my teeth into UWP and developing a simple app in C# using VS2017 v15.6.4, on the latest release of Windows 10.

运行该应用程序时,我发现其内存使用量随着时间的推移持续增加.

When running the app I notice its memory usage continues to increase over time.

经过大量的代码配对,我得出的结论是这是由页面导航调用引起的,例如:

After a lot of pairing back of the code, I've come to the conclusion that this is being caused by page navigation calls, such as:

Frame.Navigate(typeof SomePage);
Frame.GoBack();
Frame.GoForward();

创建和观察此过程非常容易...

It is very easy to create and observe this process...

1)在VS2017中,创建一个新的Blank App(通用Windows)项目,将其命名为PageTest.

1) In VS2017, create a new Blank App (Universal Windows) project, call it PageTest.

2)将新的空白页添加到项目中,并将其命名为"NewPage".

2) Add a new Blank Page to the project, naming it 'NewPage'.

3)将以下代码添加到MainPage.xaml.cs:

3) Add the following code to the MainPage.xaml.cs:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class MainPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public MainPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(NewPage));
        }
    }
}

4)将以下(几乎相同的)代码添加到NewPage.xaml.cs:

4) Add the following (almost identical) code to NewPage.xaml.cs:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class NewPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public NewPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(MainPage));
        }
    }
}

您可以看到这个简单的测试应用程序包含2个页面,并且在运行时,该应用程序将以每秒100次的速度(通过计时器)自动在两个页面之间导航,直到您关闭该应用程序.

You can see that this simple test app contains 2 pages, and when it runs, the app will automatically navigate between the two pages at the rate of 100 times per second (via the timers) until you close the app.

5)生成并运行该应用程序.还要运行任务管理器,并记下该应用程序的初始内存占用量.

5) Build and run the app. Also run Task Manager and note the app's initial memory footprint.

6)去煮一杯咖啡.当您回来时,会看到内存使用量增加了.而且它将继续增长.

6) Go and make a cup of coffee. When you come back you'll see the memory usage has grown. And it will continue to grow.

现在,我知道这个示例是不现实的,但是在这里纯粹是为了证明我怀疑是影响大多数(如果不是全部)UWP应用程序的根本问题.

Now I know this example is unrealistic, but it is here purely to demonstrate what I suspect is a fundamental problem affecting most (if not all) UWP apps.

尝试一下...

运行Windows 10设置应用程序(由Microsoft开发的UWP应用程序).再次注意,它是任务管理器中的初始内存占用量. (在我的工具包中,此大小大约为12.1 MB).

Run the Windows 10 Settings app (a UWP app developed by Microsoft). Again, note it's initial memory footprint in Task Manager. (On my kit this starts at about 12.1 MB).

然后反复单击系统设置"图标...,然后单击后退"按钮...,然后单击系统设置"图标...,然后单击后退"按钮...,您便会明白.并且注意内存占用量也会增加.

Then repeatedly click on the System Settings icon... then the Back button... then the System Settings icon... then the Back button... You get the idea. And watch the memory footprint also increase.

几分钟后,我的"MS设置"应用程序的内存消耗上升到90 MB以上.

After a few minutes of doing this, my MS Settings app memory consumption went up to over 90 MB.

这种内存消耗似乎与UWP页面的复杂性有关,如果您开始向页面中添加大量XAML控件(尤其是图像控件),则它会迅速增加.不久之后,功能丰富的UWP应用就消耗了1-2GB的内存.

This memory consumption seems to be related to UWP page complexity and it goes up rapidly if you start adding a lot of XAML controls to your pages, especially Image controls. And it doesn't take long before my feature rich UWP app is consuming 1-2GB memory.

因此,这个问题"似乎会影响所有基于框架的UWP应用.我已经在3台不同的PC上与其他UWP应用程序进行了尝试,但在所有这些PC上都遇到了相同的问题.

So this 'problem' seems to affect all frame based UWP apps. I've tried it with other UWP apps on 3 different PC's and I see the same problem on them all.

使用功能丰富的应用程序,内存消耗变得如此糟糕,以至于我现在正在考虑完全放弃Page导航,并将所有内容放到MainPage上.这不是一个令人愉快的想法.

With my feature rich app, memory consumption has got so bad that I'm now considering scrapping Page navigation altogether and putting everything on the MainPage. Which is not a pleasant thought.

不可行的潜在解决方案...

我碰到过其他文章,描述了类似的问题,并且尝试了一些提议的解决方案,这些都没有任何区别...

I've come across other articles describing a similar issue and there are proposed solutions that I've tried, which don't make any difference...

1)将以下两行之一添加到.xaml页面定义中无济于事...

1) Adding either of the following lines to the .xaml page definitions does not help...

NavigationCacheMode="Required" 

NavigationCacheMode="Enabled" 

2)切换页面无济于事时,手动强制执行垃圾回收.所以做这样的事情没什么...

2) Manually forcing garbage collection when switching pages does not help. So doing something like this makes no difference...

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    GC.Collect();
}

有人知道是否有解决方案,还是UWP应用程序的根本问题?

推荐答案

在提供的repro代码中,您将继续向前导航,这将创建无限的页面实例导航Backstack(请检查Frame.BackStack.Count).由于这些实例存储在内存中,因此应用程序的内存使用量自然会不受限制地增长.

In the repro code provided you keep navigating forward, which will create an infinite navigation backstack of page instances (check Frame.BackStack.Count). Since those instances are stored in memory the app's memory usage will naturally grow unbound.

如果您更改代码以导航回MainPage,并因此使后退堆栈深度保持为2,则反复进行来回导航不会明显增加内存.

If you change the code to navigate back to MainPage, and therefore keep the backstack depth at 2, the memory will not grow noticeably with repeated back and forth navigation.

编辑 但是,如果我们在更长的时间内观察到这种情况,则会发现内存的增加(在我的测试中,每个导航1.5KB).这是已知的平台代码泄漏,从Windows 10 Update 1803开始尚未解决.

EDIT However, if we observe this over a longer period of time there is a measurable increase of memory (1.5KB per navigation in my testing). This is a known leak in platform code that has not yet been addressed as of Windows 10 Update 1803.

在这里共享测试项目的更新版本:

The updated version of your test project is shared here:

以下是NewPage.cs的代码: https://1drv.ms/u/s! AovTw​​KUMywTNoYVFL7LzamkzwfuRfg

Here is the code for NewPage.cs: https://1drv.ms/u/s!AovTwKUMywTNoYVFL7LzamkzwfuRfg

public sealed partial class NewPage : Page
{
    DispatcherTimer timer = new DispatcherTimer();

    public NewPage()
    {
        InitializeComponent();
        timer.Interval = TimeSpan.FromSeconds(.01);
        timer.Tick += Timer_Tick;
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        timer.Start();
        long managedMem = GC.GetTotalMemory(true);
        ulong totalMem = Windows.System.MemoryManager.AppMemoryUsage;
        System.Diagnostics.Debug.WriteLine(string.Format("Managed Memory: {0} / Total Memory: {1}", managedMem, totalMem));
    }

    private void Timer_Tick(object sender, object e)
    {
        timer.Stop();
        Frame.GoBack();
    }
}

如果在您的真实应用程序中,您仅在几个导航周期后就观察到MB大小的泄漏,则这不是由于上述平台错误,而是由于需要在特定应用程序中使用VS进行其他调查例如内存分析器.通常,由于应用程序代码中的循环引用或静态事件处理程序,可能导致泄漏.调试这些错误的一个很好的第一步是查看强制GC时页面的终结器是否按预期被命中.如果不是,请使用VS内存分析工具来确定哪些对象正在泄漏以及谁在坚持.这些数据将有助于在特定情况下在应用代码中查明根本原因.通常,这是由于循环引用或未取消订阅静态事件处理程序造成的.如果您可以分享对实际应用进行性能分析的信息,很乐意为您提供更多帮助.

If in your real app you observe a MB size leak after just a couple of navigation cycles then this is not due to above mentioned platform bug, but due to something else that needs to be investigated in the specific app, with the VS memory profiler for example. Often times leaks can be caused due to circular references or static event handlers in the app code. A good first step to debug these would be see if the page's finalizer gets hit as expected when forcing a GC. if not, use the VS memory profiling tools to identify what objects are being leaked and who is holding on to that. That data will help to pinpoint the root cause in the app code for that specific case. Typically those are due to circular references, or static event handlers not being unsubscribed. Happy to help more with this if you can share info from profiling the actual app.

这篇关于浏览页面时,所有UWP应用程序都会泄漏内存吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆