2012-10-15 131 views
5

我在C#中編寫了一個長的TCP連接套接字服務器。在我的服務器內存中出現尖峯。我使用dotNet Memory Profiler(一種工具)來檢測內存泄漏的位置。 Memory Profiler表示私有堆是巨大的,並且內存如下所示(數字不是真實的,我想要顯示的是GC0和GC2的孔非常巨大,數據大小正常):什麼是GC孔?

Managed heaps - 1,500,000KB 
      Normal heap - 1400,000KB 
       Generation #0 - 600,000KB 
        Data - 100,000KB 
        "Holes" - 500,000KB 
       Generation #1 - xxKB 
        Data - 0KB 
        "Holes" - xKB 
       Generation #2 - xxxxxxxxxxxxxKB 
        Data - 100,000KB 
        "Holes" - 700,000KB 
      Large heap - 131072KB 
       Large heap - 83KB 
       Overhead/unused - 130989KB 
      Overhead - 0KB 

Howerver,什麼是GC孔? dotNet的內存分析器的機制的文檔明確的「洞」:

「孔」代表內存在兩個分配 實例之間使用。當堆未完全壓縮時,由於 固定實例或垃圾收集器中的優化,會出現「孔」。

我想知道的是:

  1. 「漏洞」出現什麼樣的分配2個實例之間?
  2. 什麼樣的實例被固定?
  3. 如何壓縮堆?

我希望有人能解釋它。

+2

我懷疑該文章是關於不同類型的孔。 – CodesInChaos

+4

「」空洞「表示在兩個分配的實例之間未使用的內存。由於固定實例或垃圾收集器中的優化,當堆未完全壓縮時出現」空洞「。 [來自.NET內存分析器文檔](http://memprofiler.com/onlinedocs/default.htm?turl=managedheaps.htm) – CodesInChaos

+2

爲什麼有這麼多人提出這個問題?作者的問題不清楚。基於編輯它也出現,他不知道他在說什麼。 –

回答

4

A pinned object是不允許在內存中移動的。在處理非託管代碼時,通常需要這樣做,這需要您傳入指向內存中某個結構的指針 - 默認情況下,垃圾收集器可以自由移動該結構以便更好地管理內存,但是如果在「我們給了一些非託管代碼一個指向該結構的指針,然後如果它移動了非託管代碼將不會再指向正確的結構,從而導致意外的行爲。

解決方法是「固定」該對象,告訴GC它不應該移動它。

你不能明確地壓縮堆,當執行完全或部分採集(除了LOH)之外,GC應該如此這般 - 固定大量對象會使其難以成功管理這個然而。有關GC的更多詳細信息,請參閱Garbage Collector Basics and Performance Hints

+1

值得注意的是,網絡連接通常是不受管理的資源,因此如果提問者的「TCP連接套接字服務器」不能非常仔細地管理其連接,並且處理大量連接,這可能是導致大量固定對象。 –

+0

所有插座在使用後都會關閉。我認爲還有一些其他非託管資源已經分配並且未被處置。 – tianyi