偶尔我们的客户在应用程序中遇到了内存不足异常。由于我们记录他们的操作,因此我们可以大致重现他们所做的事情,但是如果我这样做并使用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,here和here,但我没有找到令人满意的答案。
更新:添加了示例堆栈跟踪和堆碎片图表
没有唯一的触发内存不足异常的地方,但由于有人要求,我添加了一个堆栈跟踪:
下面这张来自dotMemory的图表展示了使用该工具工作约一个小时后的LOH碎片情况:
应用程序的一个相关属性是它处理测量时间序列(存储在数组中的DateTime和double配对)。这些对象可能足够大以存储在大对象堆(LOH)中。因此,堆碎片化确实会发生,但是在对此进行分析时,这似乎并不是什么大问题。LOH的大小小于100MB,包括空洞。
可能在内存不足异常抛出后会调用垃圾回收器(GC)吗?我认为,在未满足的内存分配请求的情况下,只有在GC无法收集足够的内存时才会抛出异常。但是,与分配在第0代堆中的内存相比,分配在LOH中的内存可能会有所不同吗?
有人有想法如何解决这个问题吗?
我们正在使用VS 2010 SP1和.NET 4.0。 该问题可能与此处提出的问题相关here,here和here,但我没有找到令人满意的答案。
更新:添加了示例堆栈跟踪和堆碎片图表
没有唯一的触发内存不足异常的地方,但由于有人要求,我添加了一个堆栈跟踪:
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碎片情况: