什么时候由.NET进程分配的内存被释放回Windows

安装程序

.NET为分段的每一代堆(0,1,2,LOH)分配内存,以便在启动时获得连续的内存块,并在收集之后尝试满足分配请求。

这个分配给每个堆的内存可能会随着应用程序“升温”而平稳下来,除了第2代和大对象堆以外。 在垃圾收集期间,每个堆(0,1,2)都被扫描和压缩,除了刚刚扫过的大对象堆(LOH)之外。

我理解集合的“扫描”部分意味着GC确定哪些对象不再是根源,并且可用于收集(或定稿),而“紧凑”意味着在堆中仍然活着的地址被重新组织可用的剩余堆有更多可用的连续内存。

由于超过了堆中每个段的预算,.NET将分配另一个段来完成分配(如果可能的话)。

问题

我的问题归结为每个堆中的内存会发生什么情况,而不是由应用程序 (提交)使用,但仍保留.NET? 什么时候释放回操作系统?

我相信这是一个过程可能会消耗大量内存的情况(虚拟大小非常大,但是私有字节很小),但是在检查其堆时大部分是可用空间 。 另外需要注意的是,堆总大小也可能相当小 ,并且不考虑进程消耗的内存。

没有阻塞的终结器,所有看起来都很健康的进程 – 它可能已经运行了几个星期,然后触发监视器警报(例如)。

尝试进一步澄清问题,如果您阅读了Tess .NET内存pipe理 – 餐厅类比 ,如果表是堆段,那么餐厅是否会丢失表(例如,免费的堆段)?

编辑

  1. 删除了工作组和鸡只的混淆参考
  2. 添加了对Tess餐厅类比的参考

Solutions Collecting From Web of "什么时候由.NET进程分配的内存被释放回Windows"

我的答案是 – 没关系。 操作系统为应用程序(运行.NET运行时)提供虚拟内存 这不是“真实”的记忆。 操作系统可以将虚拟内存的每一页放在任何它喜欢的地方 – 在处理器上,在主内存中,在磁盘上。 因此,应用程序可能使用的内存数量超过了系统内存的数量,操作系统会将所需的位复制到磁盘以确保应用程序继续运行(取决于某些寻址和技术限制)。

操作系统管理系统上所有进程的虚拟内存,并确保一个程序不会占用系统上的所有内存而损害其他程序。 当.NET运行时要求系统中的内存在堆中使用,但是不使用它时,这个内存将(如果系统空闲RAM空间不足)移动到磁盘上,因为它没有被访问。

澄清通过电子邮件从苔丝 🙁重点我的)

段的大小在整个应用程序的过程中保持不变,但有两点需要考虑。

  1. 一个段的分配是一个虚拟分配 ,这意味着虽然我们保留了虚拟内存 ,但我们只承诺我们实际使用的内容,所以用于一个段的私有字节与段大小不一样,这意味着在GC之后,你的私人字节将下降,而你的虚拟字节将保持不变。

  2. 当一个段不再使用时,即如果你遇到一段GC中的所有东西,以便它不再包含任何.net对象,虚拟分配将返回给操作系统。

采取信仰,然后堆段(餐厅表)将返回到操作系统。

我不知道这个答案,但我怀疑.NET不释放它的堆,直到进程退出(可能在卸载AppDomain,猜测)。 这只是基于我观看perfmon .NET内存计数器。 GC总字节计数器至少在我的应用程序中显示,保留字节在我的应用程序的整个生命周期内略微上升和下降,如约30MB。

而且,如果GC在服务器模式下运行,也许.NET会更频繁地释放内存。