固定内存导致 C# WebApi 中出现碎片

Pinned memory causes fragmentation in C# WebApi

我们有一个用作反向代理(转发请求和响应)的 Web 应用程序。这是一个更大平台的一部分,因此有相当多的电话通过那里。该应用程序在 IIS 上 运行,我们使用 ASP.NET WebApis ApiController 接收并使用 HttpClient 重新发送调用(.NET 4.6.1 上较新的 NuGet 包)。我们已禁用 IIS 工作进程回收。

在生产中,我们可以看到大约一周内内存使用量不断增长,然后保持在较高水平。有时我们会遇到 OutOfMemoryExceptions。使用 R# dotMemory 探查器我们找不到内存泄漏,但我们可以看到第 0 代到第 2 代对象存在巨大的碎片(高达 99%!)。我们假设这与 dotMemory 标记为固定的 OverlappedData 对象有关。

有一些 post 处理此类问题,一个很好的是 http://www.ahuwanya.net/blog/post/Buffer-Pooling-for-NET-Socket-Operations - 摘要是碎片与 IO 操作的缓冲区固定有关。所以基于此我们有一些疑问:

  1. 我们如何引入缓冲池,如 post 中所示,带有用于 ApiController 和 HttpClient 的套接字?
  2. 我们如何强制释放固定内存,例如通过关闭连接 - 而不会造成显着的性能损失?
  3. 我们如何通过获取有关固定内存的更多详细信息来确保假设是正确的?我们发现了一些有关使用 Perfmon 记录堆栈跟踪的信息,但我们将不胜感激更详细的指南。

当然,任何其他有助于我们缩小和解决问题的建议、提示或评论也将受到赞赏。请注意,我们想解决这个问题,但没有解决方法(例如每天重新启动 IIS 工作进程)。

在我们当前的版本中,我们不再有这个问题。我们对此没有真正的解释——唯一似乎改变的是我们删除了一些 "volatile" 定义。这可能是原因吗?也许是的——事实上我们假设它是,但没有真正的证据。根据文档,尚不清楚 volatile 是否会阻止内存优化,但从理解来看很有可能。所以我们就这样接受吧...