C#内存溢出异常 - 警告策略

8
在一个复杂的多线程应用程序中,我每周可能会遇到一次内存不足异常。该应用程序通过多个套接字发送/读取大量数据,其中读取的数据被缓存以避免网络卡缓冲区溢出。
分析内存异常的最佳策略是什么?在正常运行时,进程资源管理器中显示的应用程序大小为“所有堆中的总字节数”高达1.5 GB。
有没有一种策略可以使用一个线程每秒轮询下面两个选项之一来了解何时开始分析问题:

GC.GetTotalMemory()

或者

PrivateMemorySize64()

我还没有研究商业分析工具,我有些担心它们会对性能产生影响,并可能导致错误结果的分析。

1
你们的缓存是如何工作的?我建议你们考虑一种不同的分配策略来优化缓存。 - CodesInChaos
请澄清一下,您知道是什么导致了内存不足异常吗?您只是想找到一种方法来配置应用程序中的缓存,以避免出现这种情况吗?还是说您不知道具体原因,想要调试问题? - svick
4个回答

3
你的内存可能会因为众多字符串操作或其他创建和释放小块内存的操作(例如装箱/拆箱)而被分段。
当CLR无法分配足够大的空闲内存块时,您将得到此异常。
我使用“CLR Profiler”并检查内存分配情况。如果您看到许多白色点(空闲块)和没有大型空闲块,则需要开始查看您如何分配对象。
例如,在将一个字符串赋值给另一个字符串之前,请先检查这些字符串是否不同。在所有情况下使用StringBuilder,消除装箱和其他内存优化。
我使用这种技术,完全消除了异常,除了二进制反序列化的已知问题。
http://msdn.microsoft.com/en-us/magazine/cc163856.aspx中重新发现您管理代码中的内存优化的失落艺术。
http://msdn.microsoft.com/en-us/magazine/cc163528.aspx中调查内存问题。
在Visual Basic .NET中进行性能优化,请参考http://msdn.microsoft.com/en-us/library/aa289513(v=vs.71).aspx。

2
大多数字符串应该是可重定位的,因此不应该引起内存碎片化。LoH 碎片可能是一个问题,但如果您正在使用许多足以结束在 LoH 上的字符串,则可能正在做一些错误的事情。 - CodesInChaos
@weismat;使用交错数组而不是多维数组,避免重复/不必要地创建对象等等。请查看我在答案中添加的链接。确保您查看http://msdn.microsoft.com/en-us/magazine/cc163528.aspx中的调查内存问题 - AMissico
1
@AMissico,我认为你没有明确普通堆和大对象堆(LOH)之间的区别。在普通堆中,对象可以始终被重新定位。而在 LOH 中的对象则永远不会被重新定位。当从 LOH 中分配内存时,你需要找到一块连续的虚拟内存空闲块,否则就会出现 OOM(Out of Memory)。这就是为什么 LOH 的碎片化可能成为一个问题,但普通堆的碎片化却不会。 - svick
@CodeInChaos,没错,我忘记了那些情况,但它们应该非常罕见。我承认我倾向于过度使用像“总是”这样的强烈词语。 - svick
如果堆中的对象总是可以被重新定位,那么当应用程序域有足够的空闲内存时,就不会抛出内存不足异常。LOH 可以从堆中获取额外的内存来增长。如果由于堆中的碎片而无法使 LOH 增长,则会发生内存不足异常。 - AMissico
显示剩余3条评论

1

你可以考虑安装Windows调试工具并使用ADPlus

ADPlus.vbs(ADPlus)是来自Microsoft产品支持服务(PSS)的一种工具,可用于解决任何停止响应(挂起)或失败(崩溃)的进程或应用程序。

基本上,你可以设置监视应用程序,当它崩溃时,它将捕获一个转储文件,然后你可以使用WinDBG/SOS进行分析。


我可能会选择这个方法 - 我想我会将它添加到我的计划任务列表中,这样它每天都会开始,因为每天都需要一个新的开始(因为.exe文件也是每天启动)。 - weismat

1

您可以使用MemoryFailPoint来尝试在给定操作上提供一些保证。

但我建议隔离您的应用程序运行的进程,如果有64位选项,可以转换到64位,并且您可能需要考虑降低一些性能以给您合理的内存使用保证。


0

3
仅供参考,这是来自弱引用指南的内容:"避免将弱引用作为内存管理问题的自动解决方案。相反地,开发一个有效的缓存策略来处理您的应用程序对象。" - james lewis
有很少的地方可能需要弱引用 - 我认为我会将过程分成两个部分,首先将可用数据空间加倍。出于行政原因,我迄今避免了这种情况。 - weismat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接