3

我正在运行一个应用程序,它表现出一些非常特殊的问题。它可以正常运行大约 2.5 小时,然后突然非托管内存开始增长,并且增长迅速。在大约半小时左右的时间内,应用程序崩溃了。

应用程序未使用任何非托管 DLL。它正在与外部应用程序通信。它使用套接字(通过流使用)写入并通过 WCF 流读取。

我用 ANTS 对其进行了分析。非托管内存利用率的突然变化非常惊人;它永远保持完全平坦,然后突然开始上升并以稳定的速度继续上升,直到应用程序失败。托管内存中似乎没有什么不合适的。

鉴于我不是故意使用非托管代码,因此很难确定泄漏的来源。蚂蚁没有帮助。当代码从一开始就不是稳定增加时,很难清理代码的问题(应用程序一直处于空闲状态,尽管它确实每秒通过套接字用非常少量的数据 ping 它的服务器一次)。

再次迭代,这段时间应用程序和服务器都处于空闲状态;这是在一个隔离的测试系统(服务器和客户端)上运行的。客户端是泄漏的那个。

4

2 回答 2

3

您可能希望使用 DebugDiag 来监视内存泄漏,并提供有关分配的内容、数量以及来自哪些调用堆栈的信息。简而言之:

在进程开始(或重新启动)后不久,请执行以下操作:

  1. 打开调试诊断。
  2. 取消向导。
  3. 转到进程选项卡。
  4. 右键单击所需的进程。
  5. 选择监控泄漏。
  6. 单击确定。

进程运行一段时间后,内存问题很明显:

  1. 转到调试诊断
  2. 如果它仍未打开,请退出向导。
  3. 转到进程选项卡。
  4. 右键单击与第 1 部分相同的进程。
  5. 选择创建完整用户转储。
  6. 记下转储的位置。

此外,如果在捕获内存转储之前重新启动进程,则必须重新启用泄漏监控。

一旦你有了转储:

  1. 转到调试诊断。
  2. 转到“高级分析”选项卡。
  3. 选择顶部的“MemoryAnalysis.asp”脚本。
  4. 单击底部的“添加数据文件”,然后选择之前创建的转储。
  5. 单击“开始分析”并查看结果。

获得这些信息后,您应该能够确定内存分配的来源,并希望能够确定问题的原因。

您可以从以下资源中找到更多信息:

于 2011-10-12T19:09:13.303 回答
0

我们最终发现了问题。事实证明,我们在两者之间有一个套接字连接,并且在空闲阶段我们会发送一个 KeepAlive 数据包以防止监听器自动断开连接。但是,在闲置一段时间后,通过 WCF 的一些特殊超时,套接字正在服务器端关闭。

所以基本上每次 DispatchTimer 触发时,keep-alive 数据包都会被写入套接字,但显然它会阻塞。这不会阻止下一个 DispatchTimer 做完全相同的事情。虽然看起来它看起来更大,但那些小数据包正在迅速建立并吃掉所有非托管内存,我推测套接字的缓冲区(我相信我们正在使用 NetworkStream 进行连接)。随着逻辑上的一些转变,问题就消失了。

感谢您的所有投入,非常感谢!

于 2011-11-04T11:21:48.600 回答