1

我正在尝试使用 .Net AppDomain 类的MonitoringSurvivedMemorySize属性。

唯一的问题是我看不到我的应用程序从该属性接收的值如何符合 msdn 上给出的属性描述。

我观察到的差异包括属性返回的值我知道太低,因为返回的值与先前调用返回的值不同,并且在这两个调用之间,AppDomain 引用的内存量从未像新的返回值。

我在 SO、google 和 connect.microsoft.com 中搜索了“AppDomain Monitoring”,但找不到任何似乎与上述特定问题相关的内容。

为了确保这与我的应用程序的其他部分没有任何关系,我使用以下代码创建了一个新的 ConsoleApplication:

class Program
{
    static void Main(string[] args)
    {
        Console.WindowWidth = 133;

        AppDomain.MonitoringIsEnabled = true;

        var Queue = new Queue<byte[]>();

        var BlockSize = (int)1e+6; 

        var ToggleAllocation = true;

        while (true)
        {
            if (Console.KeyAvailable)
            {
                var Input = Console.ReadKey(true);

                if (Input.Key == ConsoleKey.Escape)
                {
                    break;
                }

                if (Input.Key == ConsoleKey.C)
                {
                    GC.Collect();
                    Console.WriteLine("Collect");
                }

                ToggleAllocation = !ToggleAllocation;
            }

            Thread.Sleep(100);

            if (!ToggleAllocation)
            {
                continue;
            }

            Queue.Enqueue(new byte[BlockSize]);

            while (100 < Queue.Count)
            {
                Queue.Dequeue();
            }

            var ExpectedLowerBound = Queue.Count * BlockSize;

            var MonitoringSurvivedMemorySize = AppDomain.CurrentDomain.MonitoringSurvivedMemorySize;
            var MonitoringTotalAllocatedMemorySize = AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize;

            Console.WriteLine(
                "Queue.Count=" + Queue.Count.ToString() +
                ", SurvivedMemorySize=" + MonitoringSurvivedMemorySize.ToString() +
                ", TotalAllocatedMemorySize=" + MonitoringTotalAllocatedMemorySize.ToString() +
                ", ExpectedLowerBound=" + ExpectedLowerBound.ToString());
        }
    }
}

这个函数只是不时地分配一些内存以确保最终会发生 gc 并打印出 MonitoringSurvivedMemorySize 接收到的值。

为了确保问题不是由于某些调试器“功能”引起的,我将项目切换到默认发布配置并从资源管理器运行程序。

当我运行这个程序时,MonitoringSurvivedMemorySize在一些迭代中返回 0,然后在一些迭代之后(我假设在第一次 gc 之后)一个符合我期望的更高值。但经过更多次迭代后,返回值会跳回零。它还返回不同于零但有时远低的值。

我将目标框架设置为“.NET Framework 4 Client Profile”

我究竟做错了什么?

可以复盘吗?

4

2 回答 2

0

根据文档(来自您提供的链接),您应该期望仅在完全阻止收集后更新统计信息。尝试在您的测试台中添加对GC.Collect的调用。

于 2012-09-26T08:35:30.117 回答
0

我使用 .NET Framework 4.5 遇到了同样的问题,并将其作为错误提交给微软。现在他们提供了答案并修复了它(对于 .NET Framework 4.5)

链接到微软的票:http ://connect.microsoft.com/VisualStudio/feedback/details/765296/appdomain-monitoringsurvivedmemorysize-property-returns-wrong-value-after-gen-0-collection

以下引用来自上面链接的页面:

这是一个文档错误,而不是 GC 错误。http://msdn.microsoft.com/library/system.appdomain.monitoringsurvivedmemorysize(v=vs.110).aspx上的文档 被修改为:

“每次垃圾收集都会更新统计信息。但是,只有在完整的阻塞收集之后才能保证它们是准确的;也就是说,包含所有代的收集并在收集发生时停止应用程序。例如,GC。 Collect() 方法重载执行完整的阻塞收集。(并发收集发生在后台,不会阻塞应用程序。)"

--Ron Petrusha 公共语言运行时用户教育微软公司

由于观察到的响应时间较长,我将避免在微软要求对 .NET 4.0 进行澄清,而是在此强硬地宣布这是对 OP 的有效答案。

于 2014-04-05T16:28:43.123 回答