Language agnostic 垃圾收集能有效地利用巨大的内存吗?

Language agnostic 垃圾收集能有效地利用巨大的内存吗?,language-agnostic,garbage-collection,Language Agnostic,Garbage Collection,这与其说是一个实践问题,不如说是一个理论问题。我知道GC目前正在处理使用1、2或3 Go内存的大进程,但我想知道,从理论上讲,是否有可能使用具有真正巨大内存(1000 Go或更多)的高效GC 我问这个问题是因为,即使GC可以逐步运行其算法,它也需要等待扫描完所有对象后再释放一个对象,以确保没有其他对象使用它。因此,在一个非常大的系统中,逻辑上释放内存的频率应该更低。如果内存非常大,未使用的对象将很少被释放,GC将不再感兴趣 你知道关于这个主题的研究或文章吗?浏览一下关于垃圾收集的基本知识 有不同

这与其说是一个实践问题,不如说是一个理论问题。我知道GC目前正在处理使用1、2或3 Go内存的大进程,但我想知道,从理论上讲,是否有可能使用具有真正巨大内存(1000 Go或更多)的高效GC

我问这个问题是因为,即使GC可以逐步运行其算法,它也需要等待扫描完所有对象后再释放一个对象,以确保没有其他对象使用它。因此,在一个非常大的系统中,逻辑上释放内存的频率应该更低。如果内存非常大,未使用的对象将很少被释放,GC将不再感兴趣


你知道关于这个主题的研究或文章吗?

浏览一下关于垃圾收集的基本知识


有不同的算法,据我所知,没有一种算法需要扫描所有内存。例如,在Java和.NET中,垃圾收集器首先假定所有对象都是垃圾。然后,它识别根(始终处于活动状态的对象),并从此处遍历对象图,将任何可到达的对象标记为活动对象。一旦标记了所有可访问的对象,它们就会被压缩,从而有效地增加可用内存

因此,执行垃圾收集所需的时间并不取决于进程寻址的总内存,而是取决于活动对象图的大小。死亡物体的数量是完全不相关的,因为它们甚至没有被考虑

请参阅以获得一个好的解释


编辑:由于作者改变了问题,这个回答有点失去了相关性。不过,我还是把它留作文档参考。

即使应用程序会使用更多内存,对象的数量也不会有太大变化。它将主要使用更大的对象,而不是更多的对象

因此,扫描活动引用不会花费太多时间。只需要扫描活动对象,它们之间没有任何内容


随着可用内存的增加,GC运行的频率当然会降低。收集未使用的对象仅仅是为了将内存使用量保持在最低限度是没有意义的。拥有大量未使用内存的计算机不会运行得更快。

事实上,我认为垃圾收集对于内存需求非常大的系统来说是一个更大的好处。到目前为止,我的经验已经满足了这一点(尽管我还没有达到数千GB的使用率,只有几十GB)

通常,使用大量内存的系统使用的是大量对象集合,因此通常分配数量相似,但单个分配非常大。这使得GC性能与使用较少内存的系统相当,因为GC性能。实际上与根对象的数量有关,而不是对象的总大小


然而,当您进行非常大的内存分配时,传统系统往往会遇到很多内存碎片问题。许多垃圾收集器(不幸的是,不是.NET的大型对象堆)会在收集周期中进行内存压缩,这实际上可以为大型内存使用系统提供巨大的好处,尤其是随着时间的推移。

堆内存越大,垃圾收集器的效率越高。为了避免长时间的暂停,您需要任何明智的现代收集器,它可以增量工作。(一个简单的这样的收集器是打包的。)


有关这方面的好文章,请参阅Andrew Appel。

许多系统也采用分代垃圾收集。分代垃圾收集根据对象创建的时间将其池入桶中。理论上,刚创造出来的物体比记忆中持续数天的物体更容易被清理。然后,可以根据应用程序的内存配置文件对垃圾收集系统进行调优。由于内存中的对象是根据它们的年龄进行扣带的,所以真正的长寿命对象(如引用表)可以不那么频繁地进行检查,因此不会给垃圾收集器带来相同的负载


Jacob

你能在这里为我们总结一下这篇文章对这个问题的具体回答吗?是的,尽管我相信它实际上与引用的数量成正比,而不是与对象的数量成正比(即,对同一对象的100000000个引用数组可能会对GC造成相当大的压力)。因此,在这个意义上,“图的大小”被定义为图中的边的数量,而不是节点的数量。这正是我真正想说的。它不必扫描所有对象,只需扫描所有可访问的对象。如果你创建了1GB对象,然后删除了除一个对象之外的所有对象的引用,那么GC只需要扫描那个对象(和GC根)。我们有一个Lisp应用程序,它可以占用100GB的内存,而普通的GCs又好又快。周期性的全球地面军事需要更长的时间,但有一些调整可以帮助做到这一点。(还有隔离旧区域的概念;这对我们的应用程序很有帮助,我们可以说“继续运行这个过程,但是图像中的现有内存不是垃圾,所以不必扫描它。这是Lisp特有的。)