如何最大化大对象堆中最大的连续内存块

Uns*_*ced 5 c# wcf stringbuilder out-of-memory

情况是我正在对远程服务器进行WCF调用,该服务器将XML文档作为字符串返回.

大多数时候这个返回值是几K,有时几十K,非常偶尔几百K,但很少可能是几兆(第一个问题是我无法知道).

正是这些罕见的场合引起了悲伤.我得到一个开始的堆栈跟踪:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Xml.BufferBuilder.AddBuffer()
   at System.Xml.BufferBuilder.AppendHelper(Char* pSource, Int32 count)
   at System.Xml.BufferBuilder.Append(Char[] value, Int32 start, Int32 count)
   at System.Xml.XmlTextReaderImpl.ParseText()
   at System.Xml.XmlTextReaderImpl.ParseElementContent()
   at System.Xml.XmlTextReaderImpl.Read()
   at System.Xml.XmlTextReader.Read()
   at System.Xml.XmlReader.ReadElementString()
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderMDRQuery.Read2_getMarketDataResponse()
   at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer2.Deserialize(XmlSerializationReader reader)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
Run Code Online (Sandbox Code Playgroud)

我已经阅读了,因为大对象堆刚刚变得过于分散,所以即使在调用之前快速检查StringBuilder.EnsureCapacity只会导致OutOfMemoryException被提前抛出(因为我猜测需要什么) ,它可能实际上并不需要那么多,所以我的检查引起的问题比它解决的问题多得多.有些意见认为我无能为力.

我问过自己的一些问题:

  • 使用更少的内存 - 你检查了泄漏?是.内存使用率上下波动,但没有基本增长可以保证这种情况发生.有些时候它失败了,它在之前的那个阶段取得了成功.
  • 转移较小的金额不是一个选项,这是我无法控制的第三方网络服务(或者至少需要很长时间才能解决,同时我还有问题)
  • 你能为卫生部做些什么来减少失败吗?......现在这是最富有成效的课程.这是一个32位的过程(它必须出于各种政治,技术和无聊的原因),但通常有数百兆的免费(我们看到失败的最大数量的倍数).
  • 我们可以监控LOH吗?使用perfmon我可以跟踪堆的大小,但我认为没有办法监视最大可用的连续内存块.

问题是:对于要尝试的事情有什么建议或建议吗?

Zac*_*ham 5

您可以查看绑定的TransferMode属性,以查看是否满足将其从默认值"Buffered"更改为" Streamed "或" StreamedResponse "的要求.

另外,请查看maxBufferPoolSizemaxBufferSize的值.增加内部缓冲区的大小有助于内存利用率,尤其是处理大型消息时.

如果您收到大量邮件,也可能已经设置了maxReceivedMessageSize,但我也会查看该值.

我已经看到上面的一个值,如果超过阈值,则会出现与内存相关的模糊信息.原始异常实际上是隐藏在我的应用程序中的消息.启用WCF跟踪有助于诊断问题并查看真正的错误 - 我需要增加上面一个或多个绑定属性的值.

我对你在帖子中使用的绑定没有感觉,但我相信这些设置在主要的设置中很常见.例如,查看basicHttpBinding上的MSDN文档.

如果它真的是LOH碎片,一旦调整工作耗尽,就没有什么可以做的.可能需要滚动回收应用程序来缓解它(我讨厌推荐)但如果你已经用尽了其他的努力,你可能会留下它.