我正在研究如何将gc集成到我的llvm项目中,当我阅读本文件时,有一句话让我感到困惑:
但是,对于希望重新定位可从运行代码中直接到达的对象的收集器,需要更高的标准。
我不明白移动“从运行代码中直接到达的对象”要做什么。
据我所知,“重新定位”的概念意味着gc指针引用到对象的新位置,例如:
在Java中:
Foo foo = new Foo();
foo = new Foo(); // ---> a relocation happens那么,有人能解释一下“从运行代码中直接到达的重新定位对象”想要做什么吗?
编辑:
关于“重新定位”的概念,文档没有解释它,但是我找到了本文件,它是由llvm实现的dotnet的编译器,它解释了这个概念:
如果在GC期间,GC指针可能被更新以引用对象的新位置,则GC算法正在重新定位。一种在某些区域中发现的更新指针的算法,而不是其他区域。例如,堆栈中的GC指针可能不会被更新,而堆中的GC指针可能是可更新的。如果算法从所有区域重新定位指针,则完全重新定位。当GC从某个内存区域重新定位指针时,这必然意味着GC报告在该区域是精确的。
我不知道我是否理解“搬迁”对,所以我粘贴这个信息给你。
发布于 2019-10-22 09:35:56
在本例中,本文讨论的是在堆中重新定位对象,而不是在代码中重新定位对象。
有许多不同的GC算法,所以让我们以HotSpot和G1为例。
堆被划分为两个逻辑区域(世代),即年轻的和年老的。年轻一代的收集成本很低,因为伊甸园空间被视为一个堆栈。当发生小GC时,对象将从Eden复制到幸存者空间(仍在年轻一代中)。这是对象重新定位,将其从堆的一个部分移动到另一个部分。对象也从一个幸存者空间复制到另一个幸存者空间,直到达到延长阈值。然后,如果仍然引用,就会将它们复制到老一代。
对于一个主要的GC周期,对象被重新定位在老一代中,以减少空闲空间的碎片。
对象通过对象标头访问,其中包含当前存储对象的堆中的地址。在重新定位期间,需要更新对象标头以确保其正确。为此,需要锁定对象标头,从而在更新期间阻塞应用程序线程。许多GC算法将所有这些更新组合在一起,从而导致可以看到的GC暂停。
其他算法,如来自Azul的Zing中的C4 (我为之工作),在对象头上使用一个读取屏障来消除GC暂停。如果你想要更多的细节,你可以阅读报纸,在这里http://go.azul.com/continuously-concurrent-compacting-collector
发布于 2019-10-18 09:41:09
这意味着重新定位地址位于函数局部变量中的对象。如下所示:
void doRelevantActions(final Thing t) {
for(Aspect a : t.getAspects())
if(a.isRelevant(getCurrentSituation()))
t.doSomeAction();
}通常,只有从Aspect才能到达Thing。但是在该循环中,局部变量a也到达Aspect,a可能位于CPU寄存器中,因此GC可能必须修改CPU寄存器的值才能重新定位该Aspect。
在我看来,在运行时修改函数的CPU寄存器需要的不仅仅是“更高的标准”。它需要一根魔杖。
我认为,做这类事情的GC通过确保在某些时候CPU寄存器中没有状态,所以停止运行的线程和修改所有线程的堆栈帧就足以重新定位对象。不过,修改堆栈帧仍然不是一项简单的工作。
编辑:,也许我误解了你问题的核心?也许你真的想知道什么是搬迁?假设一个对象有100个字节大,而且在某个时候,它单独占用一个8k RAM页,因为该页面上的其他任何东西都无法访问。如果GC可以将这个100字节的对象移动到另一个8k页面,那么它可以释放8k。这一行动被称为搬迁。
https://stackoverflow.com/questions/58447530
复制相似问题