gpt4 book ai didi

c# - 内存不足异常,即使似乎有足够的内存可用

转载 作者:行者123 更新时间:2023-11-30 23:33:26 25 4
gpt4 key购买 nike

有时,我们的客户会在我们的应用程序中观察到内存不足的异常。由于我们记录了他们的操作,我们可以粗略地重现他们所做的事情,但是如果我这样做并使用 dotMemory 分析应用程序,我无法重现异常并且使用的内存(大约 100 MB 托管 + 500MB 非托管)远低于限制(2GB,因为它是一个 32 位应用程序)。此外,在捕获到异常时,使用 Process.GetCurrentProcess().WorkingSet64 请求当前内存使用量,这表明内存使用量在 500 到 900 MB 之间。我知道这个数字不是很可靠,但它是另一个迹象,表明应该有足够的可用内存。

该应用程序的一个相关属性是它处理测量的时间序列(成对的 DateTime 和 double 存储在一个数组中)。这些对象可能足够大,可以存储在大型对象堆 (LOH) 中。因此,堆碎片确实发生了,但是在分析时这似乎不是是个大问题。 LOH 的大小小于 100MB 包括漏洞。

是否有可能在抛出内存不足异常后调用垃圾收集器 (GC)?我认为,在内存分配请求未得到满足的情况下,仅当 GC 未能收集到足够的内存时才会抛出异常。但是,与在第 0 代堆中分配的内存相比,在 LOH 中分配的内存可能有所不同?

有没有人知道我们如何解决这个问题?

我们使用的是 VS 2010 SP1 和 .NET 4.0。该问题可能与提出的问题有关 here , herehere , 但我在那里没有找到令人满意的答案。

更新:添加了示例堆栈跟踪和堆碎片图表

没有唯一触发内存不足异常的地方,但是既然被请求了,我就加了一个strack跟踪:

Exception of type 'System.OutOfMemoryException' was thrown.
mscorlib
at System.Runtime.Serialization.ObjectIDGenerator.Rehash()
at System.Runtime.Serialization.ObjectIDGenerator.GetId(Object obj, Boolean& firstTime)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.InternalGetId(Object obj, Boolean assignUniqueIdToValueType, Type type, Boolean& isNew)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Schedule(Object obj, Boolean assignUniqueIdToValueType, Type type, WriteObjectInfo objectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, Object memberData, WriteObjectInfo objectInfo, NameInfo typeNameInfo, WriteObjectInfo memberObjectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String memberName, Type memberType, Object memberData, WriteObjectInfo memberObjectInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, String[] memberNames, Type[] memberTypes, Object[] memberData, WriteObjectInfo[] memberObjectInfos)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
... <methods from our application follow>

dotMemory 的以下图表描述了使用该工具工作大约一个小时后的 LOH 碎片:

enter image description here

最佳答案

使用工具 vmmap我找到了问题的原因:可用于托管堆的实际内存远小于 2GB 限制。为与 MS Office 工具交互而加载的几个共享库 (~400 MB)。还有 native 代码 dll(~300MB),它们也分配非托管堆(~300MB)。还有很多其他东西,最后,托管堆只剩下大约 700MB。

由于可用内存比我原先想象的要少得多,所以 LOH 碎片的影响可能比我怀疑的要大,事实上:vmmap 显示,该内存区域中最大的空闲 block 随着时间的推移变得更小,即使可用内存保持不变。我认为,这证明碎片化是问题的原因。异常的触发器通常是我们有时用于深度复制对象的二进制序列化。它似乎会导致内存使用量达到峰值。

那该怎么办呢?我正在考虑以下选项:

  • 切换到 x64(从长远来看无论如何都会发生)
  • 切换到 .NET 4.5.1,它允许 defragment乐乐
  • 减少一般内存使用:如果还有大约 200MB 的可用空间,碎片整理似乎需要更长的时间。当一些大库没有加载时会发生这种情况。在我的实验中,我无法再触发内存不足异常。
  • 更改代码,这可能会太耗时

关于c# - 内存不足异常,即使似乎有足够的内存可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33953741/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com