【发布时间】:2011-07-11 19:50:06
【问题描述】:
设置
.NET 为每一代的堆(0、1、2、LOH)分段分配内存以获得连续的内存块,在启动时以及在收集后尝试满足分配请求时。
为每个堆分配的内存可能会随着应用程序“热身”而趋于平稳,除了可能用于第 2 代和大型对象堆。在垃圾回收期间,每个堆 (0, 1, 2) 都会被清扫和压缩,但大对象堆 (LOH) 除外,它只是被清扫。
我理解集合的“扫描”部分意味着 GC 识别哪些对象不再是根对象并且可用于收集(或终结),并且“紧凑”意味着在堆中仍然存在的地址被重新组织,以便可用的剩余堆具有更多可用的连续内存。
当超出堆内每个段的预算时,.NET 将分配另一个段以尽可能满足分配。
问题
我的问题归结为每个堆中的内存会发生什么,即 不再被应用程序使用(已提交),但仍由 .NET 保留? 什么时候发布回操作系统?。
我认为这是一个进程可能会消耗大量内存(虚拟大小很大,但私有字节很小),但在检查其堆时大部分是可用空间。作为另一个警告,堆的总大小也可能非常小,并且不考虑进程消耗的内存。
没有阻塞的终结器,并且所有进程看起来都很健康 - 它可能在触发监视器警报之前已经运行了数周(例如)。
为了进一步澄清问题,如果您阅读 Tess .NET Memory Management - A Restaurant Analogy,如果桌子是堆段,餐厅是否会丢失桌子(例如空闲堆段)?
编辑
- 删除了对工作集和鸡的混淆参考
- 添加了对 Tess 餐厅类比的参考
【问题讨论】:
-
我认为最小化不会要求任何人提供任何保留的内存(如果有时确实会发生这种情况)。据我所知,最小化只会导致 Windows 更愿意将该进程的内存交换到磁盘。
-
查看此站点:informit.com/articles/article.aspx?p=100597 "这称为非确定性终结器 — 您无法确定何时调用对象的终结器。结果是您的对象使用的任何内存或非托管资源仍处于分配状态在对象本身不再被您的程序实际使用之后的不确定时间内。"
-
@Martinho,Winform 可能挂钩最小化消息并调用 GC.Collect(),我不知道,但它可以。
-
@Ian:那不会是 Windows 要求任何东西。那将是您自己的进程决定压缩堆,从而为您的进程保留更多未使用的内存。即使该内存是“免费的”,它仍然属于您的进程,而不是操作系统。问题不在于何时发生垃圾收集,而在于垃圾收集器“释放”的内存何时返回给操作系统。
-
@Martinho - 你说得对,我(错误)记得的是进程“工作集”报告受到最小化应用程序的影响。
标签: .net windows garbage-collection memory-management