为什么"查看堆"结果与“处理内存使用情况”不匹配'在Visual Studio中

时间:2015-06-02 19:21:09

标签: c# visual-studio

我正在尝试使用Visual Studio来跟踪应用中的内存使用情况。在'诊断工具'窗口,它显示我的应用程序使用423 MB。谢谢我转到内存使用情况'和' ViewHeap',当我点击快照时,我得到了一个我的对象大小的表格。

enter image description here

但是当我添加这些数字时: = 3317228 + 403764 + 354832 + 264984 + 244836 + 195748 + 144032 + 28840 + 16452 + 13920 + 13888 + 3428 + 2100 + 20 = 5004072 = 4.77 MB

我的问题是为什么这个数字4.77MB与我在" Memory"上看到的423MB不匹配。图表。我希望左边的表格可以看到423 MB的位置。请告诉我我错过了什么?

2 个答案:

答案 0 :(得分:32)

为什么View Heap大小与内存图表大小不匹配?

有很多潜在的原因,包括 JITter 调试工具调试符号只是我的代码垃圾收集等。我们将通过两个大的。

只是我的代码

Visual Studio的 Just My Code 功能倾向于隐藏分配,异常,断点以及来自用户的任何其他非代码元数据从.PDB文件或打开的项目加载。有关详细信息,请参阅MSDN Just My Code

调试符号和工具

在Visual Studio中调试任何项目时,Visual Studio调试器会运行并分配额外的内存以允许断点异常捕获,以及其他特性。对于 true 诊断工具捕获,您应该使用Alt+F2选项或 Debug>无需调试即可启动诊断工具...... 。您还需要切换到此部分的发布模式。此步骤单独切断了图表(对我来说)从21.5MiB5.5MiB的内存,表明调试符号调试工具实质性因素。请记住,为了使Visual Studio能够捕获异常,断点和其他数据,必须将自身附加到您的流程以及流程中的所有对象。

那么,我们如何使这些数字匹配?

你真的不应该担心关于匹配的数字。 Memory Graph和View Heap图表的目的是让您看到尖峰和奇数内存波动,这可能表明程序不正确。你应该寻找那些,而不是关注两个价值观之间的差异。

也就是说,您可以采取一些步骤来获得准确结果。

真正匹配数字

如果真正想要匹配它们,我认为不能按照您希望的方式完成。但是,你可以走近一点。第一步是启动无需调试的诊断工具...... ,然后选择内存使用。选择后,点击旁边的设置齿轮,并确保 Profiler类型Mixed (Managed and Native)。然后,点击开始并拍摄一些快照,以便检查内存使用情况。完成后,停止调试并检查内存。

要检查内存,请在快照框中单击要检查的快照的左上角蓝色数字。在此页面上,单击右上角上的网格图标,然后取消选择仅我的代码折叠小对象。切换到原生堆标签并执行相同操作,取消选择仅我的代码,然后选择包含释放的分配

您应该会发现仅此一点就会使您的错误更接近实际值。 (实际值是私有字节,错误是堆大小)使用我测试的应用程序,它将总数(从两个堆)带到约{ {1}},当我在Visual Studio之外运行程序时,它与任务管理器指示的分配大致相同(此实际值为1.0265MiB,但数字小于预计误差幅度。)

包含释放分配是什么意思?基本上,当1.1211MiB清除内存时,该内存不会立即从应用程序的空间中移除。相反,它可以被其他对象释放,但仍然可以保留在应用程序中。 Garbage Collection是一个复杂的主题,超出了这个问题和答案的范围。

附加说明

内存分配,使用和测量是非常复杂的主题。不幸的是,没有很多100%简单的方法可以处理这样的情况,通常解决方案越简单,越准确,越复杂,越慢,越难以使用。

参考

MSDN Just My Code:https://msdn.microsoft.com/en-us/library/dn457346.aspx#BKMK__NET_Framework_Just_My_Code

MSDN垃圾收集:https://msdn.microsoft.com/en-us/library/0xy59wtx%28v=vs.110%29.aspx

此答案的其余部分基于我自己的实验试错,并且可能会因不同的环境而导致潜在的不准确。< / em>此处提供的步骤可能不适用于所有开发人员,并且使用 Visual Studio 2015 RC 版本 14.0.22823.1 D14REL 执行。< / p>

答案 1 :(得分:4)

该图显示整个过程的私有字节。这包括托管堆,本机堆,堆栈等...有关内存指标类型的更多信息,请参阅此答案:What is private bytes, virtual bytes, working set?

Heap View表仅显示拍摄快照时托管堆上的活动类型(无法进行垃圾回收)。要查看本机和托管堆上的类型,请切换到混合模式调试。堆视图(以及快照表中的数字)是图中显示的进程内存的子集。

调试器集成工具最适合尝试查找内存中意外增长的原因,或者跟踪应该被垃圾收集但仍然保持活动的引用的对象。

这是我在Memory工具上写的一篇博文(我为MSFT工作),解释了如何使用过时的引用来跟踪对象: http://blogs.msdn.com/b/visualstudioalm/archive/2015/04/29/diagnosing-event-handler-leaks-with-the-memory-usage-tool-in-visual-studio-2015.aspx