AppDomain.MonitoringSurvivedMemorySize的意外行为

时间:2012-09-25 20:03:30

标签: .net monitoring appdomain

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

只有问题我无法看到我的应用程序从此属性获得的值如何符合msdn上给出的属性的描述。

我观察到的差异包括Property返回一个我知道太低的值,因为返回的值与前一个调用返回的值不同,并且在这两个调用之间,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之后)有一个更高的值满足我的期望。但经过一些迭代后,返回值会跳回零。它还会返回不同于零但从远到低的值。

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

我做错了什么?

你能复制吗?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我使用.NET Framework 4.5遇到了同样的问题,并将其作为错误提交给microsoft。 现在,他们提供了一个答案并修复了它(对于.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公共语言运行时用户教育Microsoft Corporation

由于观察到的响应时间很长,我将不再要求在Microsoft 4.0上澄清.NET 4.0,而是高声宣布这是OP的有效答案。