如何准确查看每个加载项使用的内存量?

时间:2018-06-07 17:58:36

标签: outlook windbg

有没有办法让我看到每个Outlook加载项确实使用了多少内存?我在32位Office上有一些客户,他们都遇到屏幕闪烁和崩溃的问题,我怀疑我们作为一家公司已经部署了太多的插件,即使是大地址感知(LAA),他们也是如此。重新耗尽内存导致Outlook吓坏了。

我在Outlook中没有看到这样做的方法所以我创建了一个.dmp文件,我已经通过windbg打开了它,但我对这个应用程序是新手并且不知道怎么做查看特定加载项的特定内存使用情况(.dmp文件仅为outlook.exe)

2 个答案:

答案 0 :(得分:1)

以下假设使用C ++或其他" native"创建的插件。语言,至少不是.NET。

使用new语句分配的内存转到HeapAlloc()。为了找出谁分配了内存,该信息也需要存储在堆中。

但是,您无法在new语句中提供该信息,即使可能,您也需要重写代码中的所有new语句。

另一种方式是HeapAlloc()在有人想要记忆时查看调用堆栈。在正常操作中,成本太高(时间方面)和开销太大(内存方面)。但是,可以启用所谓的用户模式堆栈跟踪数据库,有时缩写为UST数据库。您可以使用随WinDbg一起提供的工具GFlags来实现。

捕获内存快照的工具是UMDH,WinDbg也可以使用。它将结果存储为纯文本文件。应该可以从那些UST中提取统计数据,但是,我不知道会有这样的工具,这意味着你需要自己编写一个。

第三种方法是使用"堆标记"的概念。但是,它非常复杂,还需要修改代码。我从未实现它,但您可以查看问题How to benefit from Heap tagging by DLL?

让我们说UST approch看起来最可行。 UST数据库应该有多大?

到目前为止,50 MB足以让我识别和修复内存泄漏。但是,对于该用例,获取有关所有内存的信息并不重要。它只需要足够的样本来支持假设。这些50 MB是在您的应用程序的内存中分配的恕我直言,因此它可能会影响应用程序。

UST数据库仅存储地址,而不存储调用堆栈文本。因此,在32位应用程序中,调用堆栈上的每个帧只需要32位存储空间。

在您的情况下,50 MB是不够的。考虑到平均深度为10帧,平均分配大小为256字节(对于int而言是4个字节,还有像字符串这样的更大的东西),你得到了

4 GB / 256字节= 16M分配

16M分配* 10帧* 4字节/帧= 640 MB UST

如果给定的假设是现实的(我不能保证),那么你需要一个640 MB的UST数据库大小。这会对您的应用程序产生很大影响,因为它会将内存从4 GB减少到3.3 GB,因此OOM会更早出现。

如果在创建故障转储时配置了UST信息,那么它也应该在DMP文件中可用。当然不在你的DMP文件中,否则你会告诉我们。但是,它没有以对统计有利的方式提供。使用UMDH文本文件恕我直言是一种更好的方法。

  

有没有办法让我看到每个Outlook加载项确实使用了多少内存?

目前没有DMP文件。使用WinDbg提供的工具仍然很难。

还有其他一些选择:

  • 禁用所有插件并测量Outlook本身的内存。然后,一次启用一个插件并使用该插件启用来测量内存。计算差异以找出插件需要的额外内存。

  • 启动时会立即崩溃吗?或者稍后,说使用10分钟后?可能是内存泄漏?识别内存泄漏可能更容易:一次启用一个插件并监视内存使用情况。使用内存分析器,而不是WinDbg。它将更容易使用,它可以绘制您需要的适当图形。

请注意,您需要定义一个清晰的过程来测量内存。某些内存只会在您执行特定操作时分配("延迟初始化")。也许你也想测量那个记忆。

答案 1 :(得分:1)

以下假设使用.NET创建插件。

使用new语句分配内存到.NET内存管理器。为了找出分配内存的插件,该信息也需要存储在.NET堆中。

.NET堆中没有可用于Windows堆管理器的UST(用户模式堆栈跟踪)数据库。此外,.NET内存管理器直接在VirtualAlloc()之上工作,因此它不使用Windows堆管理器。基本上,原因是垃圾收集。

  

有没有办法让我看到每个Outlook加载项确实使用了多少内存?

不,因为此信息未存储在故障转储中,并且没有设置启用它。

您需要的是一个特定于.NET的内存分析器。

如果你已经使用.NET和Visual Studio,也许你正在使用JetBrains Resharper。 Ultimate Edition附带了一个名为dotMemory的工具,因此您可能已经拥有许可证,只需通过控制面板进行安装("修改" Resharper安装)。

它具有(以及其他工具可能也具有)通过汇编对内存分配进行分组的功能:

Screenshot of dotMemory

屏幕截图显示了一个名为" MemoryPerformance"的应用程序分配的内存。它在对象中保留202 MB,这些对象主要是.NET框架的对象(mscorlib)。