如何防止 WCF 客户端应用程序中的 BufferManager / PooledBufferManager 浪费内存?

2024-04-28

分析一个 WCF 客户端应用程序(我没有编写,而且仍然不太了解),该应用程序通过 SOAP 与一堆服务进行通信,运行几天后会抛出 OutOfMemoryException,我发现 .net 的 PooledBufferManager 会即使应用程序内存不足,也永远不要释放未使用的缓冲区,从而导致 OOME。

这当然符合规范:http://msdn.microsoft.com/en-us/library/ms405814.aspx http://msdn.microsoft.com/en-us/library/ms405814.aspx

当缓冲池被破坏时,池及其缓冲区将被破坏 通过垃圾收集来回收。

请随意回答下面的一个问题,因为我有很多问题,其中一些是更一般性的,还有一些是针对我们的应用程序对 BufferManager 的使用的。

首先是关于(默认 Pooled)BufferManager 的几个常见问题:

1)在有 GC 的环境中,为什么我们需要一个 BufferManager 来保留未使用的内存,即使这会导致 OOME?我知道,有 BufferManager.Clear(),你可以用它来manually摆脱所有缓冲区 - 如果您有权访问 BufferManager,也就是说。请参阅下文以了解为什么我似乎无权访问。

2)尽管 MS 声称“这个过程比每次需要使用缓冲区时创建和销毁缓冲区要快得多”,但他们不应该将其留给 GC(例如其 LOH)并优化 GC ?

3)当执行 BufferManager.Take(33 * 1024 * 1024) 时,我将获得 64M 的缓冲区,因为 PooledBufferManager 将缓存该缓冲区以供以后重用,这可能 - 好吧,在我的情况下它不是,因此它纯粹是浪费内存 - 比如说,需要 34M、50M 或 64M。那么创建一个像这样可能非常浪费的 BufferManager 是否明智,它由 HttpsChannelFactory 使用(我认为默认情况下)?我不明白内存分配的性能有多么重要,特别是当我们谈论 WCF 和网络服务时,应用程序将每 10 秒 TOPS 进行一次对话,通常需要更多秒甚至几分钟。

现在有一些与我们的应用程序使用 BufferManager 相关的更具体的问题。该应用程序连接到几个不同的 WCF 服务。对于每个连接,我们都维护一个用于 http 连接的连接池,因为连接可能同时发生。

检查一个堆转储中的单个最大对象,这是一个 64M 字节数组,仅在初始化时在我们的应用程序中使用过一次,之后就不需要了,因为服务的响应仅在初始化时那么大,顺便说一句。对于我使用过的许多应用程序来说这是典型的,即使这可能需要优化(缓存到磁盘等)。 WinDbg 中的 GC 根分析产生以下结果(我将专有类的名称清理为“MyServiceX”等):

0:000:x86> !gcroot -nostacks 193e1000
DOMAIN(00B8CCD0):HANDLE(Pinned):4d1330:Root:0e5b9c50(System.Object[])->
035064f0(MyServiceManager)->
0382191c(MyHttpConnectionPool`1[[MyServiceX, MyLib]])->
03821988(System.Collections.Generic.Queue`1[[MyServiceX, MyLib]])->
038219a8(System.Object[])->
039c05b4(System.Runtime.Remoting.Proxies.__TransparentProxy)->
039c0578(System.ServiceModel.Channels.ServiceChannelProxy)->
039c0494(System.ServiceModel.Channels.ServiceChannel)->
039bee30(System.ServiceModel.Channels.ServiceChannelFactory+ServiceChannelFactoryOverRequest)->
039beea4(System.ServiceModel.Channels.HttpsChannelFactory)->
039bf2c0(System.ServiceModel.Channels.BufferManager+PooledBufferManager)->
039c02f4(System.Object[])->
039bff24(System.ServiceModel.Channels.BufferManager+PooledBufferManager+BufferPool)->
039bff44(System.ServiceModel.SynchronizedPool`1[[System.Byte[], mscorlib]])->
039bffa0(System.ServiceModel.SynchronizedPool`1+GlobalPool[[System.Byte[], mscorlib]])->
039bffb0(System.Collections.Generic.Stack`1[[System.Byte[], mscorlib]])->
12bda2bc(System.Byte[][])->
193e1000(System.Byte[])

查看 BufferManager 管理的其他字节数组的 gc 根发现其他服务(不是“MyServiceX”)具有不同的 BufferPool 实例,因此每个服务都在浪费自己的内存,他们甚至没有共享浪费。

4)我们在这里做错了什么吗?我无论如何都不是 WCF 专家,那么我们可以让各种 HttpsChannelFactory 实例都使用相同的 BufferManager 吗?

5)或者甚至更好,我们是否可以告诉所有 HttpsChannelFactory 实例根本不使用 BufferManager,并要求 GC 完成其该死的工作,即“管理内存”?

6)如果问题 4) 和 5) 无法得到解答,我是否可以访问所有 HttpsChannelFactory 实例的 BufferManager 并手动调用它们上的 .Clear() - 这远非最佳解决方案,但它已经有帮助了,在我的这样一来,在一个服务实例中不仅可以释放上述64M,还可以释放64M + 32M + 16M + 8M + 4M + 2M!因此,仅此一项就可以使我的应用程序运行更长时间,而不会遇到内存问题(不,除了 BufferManager 之外,我们没有内存泄漏问题,尽管我们确实消耗了大量内存并在过程中积累了大量数据很多天,但这不是这里的问题)


我相信我已经回答了你的问题#5:

5) 或者更好,我们可以告诉所有 HttpsChannelFactory 实例根本不使用 BufferManagers 并要求 GC 执行 它该死的工作就是“管理内存”?

有一个 MaxBufferPoolSize 绑定参数,它控制 BufferManager 中缓冲区的最大大小。将其设置为 0 将禁用缓冲,并且将创建 GCBufferManager 而不是池化的 GCBufferManager - 并且一旦处理消息,它将立即 GC 分配缓冲区,如您的问题所示。

本文讨论WCF内存缓冲区管理 http://obsessivelycurious.blogspot.ru/2008/04/wcf-memory-buffer-management.html更详细地说。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 WCF 客户端应用程序中的 BufferManager / PooledBufferManager 浪费内存? 的相关文章

  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 为什么禁止在 constexpr 函数中使用 goto?

    C 14 对你能做什么和不能做什么有规则constexpr功能 其中一些 没有asm 没有静态变量 看起来相当合理 但标准也不允许goto in constexpr功能 即使它允许其他控制流机制 这种区别背后的原因是什么 我以为我们已经过去
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • *.tlb 文件在运行时使用过吗?

    我正在开发一个通过 COM 互操作公开一些 NET API 的产品 作为构建的一部分 我们为所有此类程序集生成 tlb 文件 并将它们作为单独 SDK 包的一部分提供 我们的客户可以在我们的产品之上安装 SDK 并创建使用我们的 COM A
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 将 System.Windows.Forms.Keys 序列转换为 Char

    有没有办法转换由 Keys 枚举表示的击键序列 即System Windows Forms Keys 在一个字符中 例如 Keys Oem4进而Keys A产生 char 它一定存在于 WinAPI 中的某个地方 因为当我在文本框中按下按键
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐