什么是GC孔?

我用C#写了一个很长的TCP连接套接字服务器。 我的服务器内存中出现峰值。 我使用dotNet Memory Profiler(一种工具)来检测内存泄漏的位置。 内存分析器指示私有堆很大,内存类似于下面(数字不是真实的,我要显示的是GC0和GC2的孔非常大,数据大小正常):

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 Memory Profiler的文档确定了“漏洞”:

“Holes”表示在两个分配的实例之间未使用的内存。 由于垃圾收集器中的固定实例或优化,堆未完全压缩时会出现“漏洞”。

我想知道的是:

  1. 什么样的两个分配实例之间出现“漏洞”?
  2. 固定了什么样的实例?
  3. 如何压缩堆?

我希望有人可以解释一下。

固定对象是不允许在内存中移动的对象 。 在处理非托管代码时经常需要这样做,这需要您将指针传递给内存中的某个结构 – 默认情况下,垃圾收集器可以自由移动该结构以便最好地管理内存,但是如果它在您执行时执行此操作给了一些非托管代码一个指向该结构的指针然后如果它移动了非托管代码将不再指向正确的结构,导致意外行为。

解决方案是“固定”该对象以告诉GC它不应该移动它。

你不能明确地压缩堆,GC在执行完全或部分收集( LOH除外)时应该这样做 – 固定大量对象将使它更难以成功地管理它。 有关GC的更多详细信息,请参阅垃圾收集器基础知识和性能提示