异步套接字内存使用率高,可能存在泄漏



我正在重写服务器应用程序,对应用程序的内存使用感到困惑。早期版本是用TcpListener编写的,而新版本是普通的旧Socket。这主要是出于性能和稳定性的原因,而性能和稳定性是这个问题甚至这个问题的次要原因。

如前所述,所有内容都与AcceptAsyncSendAsyncReceiveAsync严重异步。除此之外,我将ThreadPool.QueueUserWorkItem用于实用程序任务,如AcceptAsync的初始启动和保持下一个AcceptAsync排队、处理后回写到Socket的调用,以及清理断开连接的客户端的调用。此外,我用BeginInvokeEndInvoke触发了一系列事件。

对这些断开连接的检测以及对数据可用性的主要驱动程序由我称为AvailabilityNotifier的自定义类处理,该类在ReceiveAsync上达到峰值,并且对SocketAsyncEventArgs.BytesTransferred为零的检测触发Disconnect事件。

应用程序的吞吐量很好,而且由于System.Collections.Concurrent对象的健康使用,几乎没有(相对而言)锁争用。然而,它紧紧抓住记忆,就像捕食者紧紧抓住猎物一样。

我已经进行了调试,以验证我的内部集合是否被清除,客户端套接字是否被关闭和处理,以及是否使用缓冲池而不是为每次读取创建新的缓冲区。运行一个最终执行1000个连接(100个并发)并发送/接收100000条消息的测试应用程序会将服务器进程内存膨胀到800 MB左右,即使在Windows清除了可能发生的任何TIME_WAIT之后,它也不会停止。我确信,由于你可以在下面链接的github中看到大量的ObjectDisposedException和空异常catch块,偶极代码正在启动。

我说这一切都没有引用代码,因为这里的帖子很长,所以这里有一个github:https://github.com/hoagsie/TcpServer.如果您想自己运行Program.csClientProgram.cs,也会提供它们,但主要操作在NetworkServer.csAvailabilityNotifier.cs中。我运行的示例服务器也有一个WCF服务,它可以与之对话,但它只是标准的WCF项目,没有任何修改。我只是需要它来匹配一个示例场景。

我也不确定它在某种程度上是否重要,但我确实在x64模式而不是AnyCPU/x86中构建了它。这主要是为了在目标服务器上获得资源消耗机会,但我没有注意到x86或x64中与此问题有关的行为差异。

编辑:

一位同事指出了Visual Studio中的快照工具。我以前从未见过它,它显示的内容与我一直使用的dotTrace不同。它指出了围绕SocketAsyncEventArgs对象的大量分配,这是有道理的,但它们一直在构建。我再次查看了它的成员列表,发现它有一个Dispose方法。我的问题已经过去了。我没有意识到那是一个IDisposable对象。

一位同事指出了Visual Studio中的快照工具。我以前从未见过它,它显示的内容与我一直使用的dotTrace不同。它指出了围绕SocketAsyncEventArgs对象的大量分配,这是有道理的,但它们一直在构建。我再次查看了它的成员列表,发现它有一个Dispose方法。我的问题已经过去了。我没有意识到那是一个IDisposable对象。

最新更新