2017-10-20 28 views
0

我有一個服務器應用程序重寫正在進行,並且對應用程序的內存使用感到困惑。較早的版本是用TcpListener編寫的,而新版本是舊版Socket。這主要是出於性能和穩定性的原因,這是次要的問題甚至是這個問題。異步套接字高內存使用率和可能的泄漏

如上所述,所有內容都與AcceptAsyncSendAsyncReceiveAsync嚴重異步。最重要的是,我使用ThreadPool.QueueUserWorkItem來執行實用程序任務,例如AcceptAsync的初始啓動和保持排隊的下一個AcceptAsync,處理後的呼叫寫回到Socket,以及清除斷開客戶端的呼叫。此外,我還有一系列事件發生在BeginInvokeEndInvoke之間。

檢測對於那些斷開以及用於數據可用性的主要驅動力是由我請AvailabilityNotifier其上的峯ReceiveAsync以及檢測裝置,用於SocketAsyncEventArgs.BytesTransferred爲零時觸發一個事件Disconnect的自定義類處理。

應用程序的吞吐量很好,並且由於健康的使用System.Collections.Concurrent對象,幾乎沒有(相對來說)鎖爭用。然而,它像追捕者一樣依附於記憶。

我已經調試過,以驗證我的內部集合正在清除,客戶端套接字正在關閉並處理掉,並且利用緩衝池而不是爲每次讀取創建新緩衝區。運行最終執行1,000個連接(100個併發)併發送/接收100,000個消息的測試應用程序會將服務器進程內存膨脹到800 MB左右,並且即使Windows清除可能發生的任何TIME_WAIT s也不會停止。我知道肯定diposal代碼是射擊感謝大量的ObjectDisposedException和空例外catch塊,你可以在下面鏈接的github中看到。

我說所有沒有引用的代碼,因爲這裏的帖子相當長,所以這裏有一個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對象。

回答

0

一位同事指出了Visual Studio中的快照工具。我從來沒有見過這個,它顯示的東西與我以前使用的不同,它是dotTrace。它指出圍繞SocketAsyncEventArgs物體的許多分配是有意義的,但他們不停地建造和建造。我再次查看其成員列表,發現它有一個Dispose方法。我的問題已經消失。我沒有意識到這是一個IDisposable對象。