mono / .Net GC会在收集后将免费分配的内存释放回操作系统吗?如果没有,为什么?

时间:2014-06-15 12:03:42

标签: c# memory garbage-collection

我听过很多次,一旦C#托管程序从OS请求更多内存,它就不会释放它,除非系统内存不足。例如。当收集对象时,它被删除,对象占用的内存可以被另一个托管对象自由重用,但内存本身不会返回给操作系统(例如,unix上的mono不会调用{{1} } / brk将进程可用的虚拟内存量减少到分配之前的内容。

我不知道这是否真的发生了,但是我可以看到我在linux上运行的c#应用程序在开始时使用少量内存,然后当我做一些内存昂贵的内存时,会分配更多内存,但是稍后当所有对象都被删除时(我可以通过将调试消息放入析构函数来验证),内存不会被释放。另一方面,当我再次运行内存昂贵的操作时,不再分配更多的内存。该程序只是继续使用相同数量的内存,直到它被终止。

也许这只是我对.net中的GC如何工作的误解,但如果它真的像这样工作,那为什么呢?保留分配的内存以供以后使用,而不是将其返回给系统有什么好处?它怎么能知道系统是否需要它?那么因为这种效应导致OOM崩溃或无法启动的其他应用程序呢?

我知道人们可能会回答类似“GC管理内存比以往任何时候都更好,只是不关心它”或“GC知道它做得最好”或“它根本没关系,它是只是虚拟内存“但它确实很重要,在我的2gb笔记本电脑上运行OOM(内核OOM杀手就是因为这个而开始),经常在我运行任何C#应用程序一段时间之后,因为这种不负责任的内存管理。” p>

注意:我在linux上单声道测试这个因为我真的很难理解windows如何管理内存,所以linux上的调试对我来说要容易得多,linux内存管理也是开源代码,windows内核的内存管理/ .Net对我来说相当神秘

2 个答案:

答案 0 :(得分:4)

内存管理器以这种方式工作,因为当你不需要它时,拥有大量未使用的系统内存是没有好处的。

如果内存管理器总是试图尽可能少地分配内存,那么这意味着它会毫无理由地做很多工作。它只会减慢应用程序的速度,唯一的好处就是没有应用程序正在使用的更多可用内存。

每当系统需要更多内存时,它会告诉正在运行的应用程序尽可能多地返回。当您将应用程序最小化时,也会向应用程序发送相同的信号。

如果这对Linux中的Mono不起作用,那么这是特定实现的问题。

答案 1 :(得分:3)

通常,如果应用需要一次内存,则需要再次使用。将内存释放回操作系统只是为了再次请求它是开销,如果没有别的想要内存:为什么要打扰?。它正试图针对极有可能再次想要它的情况进行优化。另外,将其释放回来需要可以交还的整个/连续的块,这对压实等事情具有非常特殊的影响:它不像"嘿,我没有使用大多数这个:回来了#34; - 它需要弄清楚哪些块可以被释放,大概是在完全收集和压缩(重新定位对象等)循环之后。