我在一台Windows CE设备上使用一个基于事务的系统,该设备使用的是Compact .NET Frameworkv3.5。我们发现,随着越来越多的事务被执行,可用的内存越来越少。显然是某种内存泄漏。
在每个事务之后,我们获取两次内存读取;一次来自操作系统( PInvoke调用),另一次来自垃圾收集器。我们发现,操作系统的读数增加了内存使用量,而GC的读数保持相对稳定(大约1MB的差异+-)。
该应用程序利用Microsoft Synchronization Services将信息存储在两个本地数据库(SQL server Compact v3.5)上,并将它们与远程服务器同步。
如果这是Windows XP,我会简单地用WinDbg连接到可执行文件,并分析堆,看看我创建的对象是否永远不会被GC,但是,我甚至不知道问题是否出在托管堆上。
所以这个问题有两个部分:
1)在托管应用程序(DataAdapters、流等)中,以这种方式泄漏内存的可能罪魁祸首是什么?
2)哪些调试工具/技术可以帮助我找到确切的问题?
我知道这不是很多,但在这个阶段,我没有比这更多的信息。
谢谢!
发布于 2010-11-17 07:36:33
有两种方法可以解决这个问题。首先是查看托管对象及其生存期。您可以使用Remote Performance Monitor来查看GC堆的快照并对它们进行比较。
您可以使用CLR Profiler检查调用树,并查看这些对象来自何处。
这两个工具通常允许您查找托管代码问题。
现在,这里重要的一点是,您说GC没有报告任何增长,这告诉我GC堆很好,而这些工具在这种特定情况下不太可能找到太多东西。尽管如此,我还是列出了这些工具,因为它们将来可能会对您(或其他阅读本文的人)有所帮助。
在你的案例中,听起来像是你有一个本机漏洞。您没有说哪种类型的内存正在泄漏-物理内存还是虚拟内存-但几乎可以肯定的是,某些内存正在进行未被释放的本机分配。我的猜测是SQL Compact是基于您所说的关于您的体系结构的内容,因为该引擎是在本机代码中实现的,并且其上有一个托管层。
我还会猜测,根本原因是您有一些小的托管对象(可能是SqlCeTransaction或SqlCeCommand),它们各自具有很小的托管内存占用空间,但正在为您进行一些本机分配,并且这些对象仍然存在。
托管工具应该允许您定位大量或不断增加的这些项,并定位阻止GC杀死它们的根源。验证您是否正在使用的所有SqlCe对象上调用Dispose也是一件很好的事情。
如果所有这些都无法找到它,您可以深入研究一些native tools,但它们根本不能很好地处理托管代码,并且不太可能给您提供太多信息。
发布于 2010-11-17 06:52:02
听起来你好像在什么地方丢了一个EndInvoke?还是不关闭你的连接?
这可能不是问题,但在我的工作中,我们只是遇到了一个类似的问题……几个丢失的EndInvoke调用在正常运行几天后完全锁定了我们的服务器……就像我们不得不关闭和硬启动机器的地方一样。
https://stackoverflow.com/questions/4199713
复制相似问题