我知道当 V8 的垃圾收集器工作时,它会从 GC 的根开始跟踪,以便标记无法访问的对象,然后将其清扫。我的问题是 GC 遍历是如何遍历这些对象的?必须有一个数据结构来存储所有可访问或不可访问的对象。位图?联表?
顺便说一句,JVM 也会这样做吗?
我知道当 V8 的垃圾收集器工作时,它会从 GC 的根开始跟踪,以便标记无法访问的对象,然后将其清扫。我的问题是 GC 遍历是如何遍历这些对象的?必须有一个数据结构来存储所有可访问或不可访问的对象。位图?联表?
顺便说一句,JVM 也会这样做吗?
艾伦秀,
Google 的 V8 堆被组织成几个不同的空间。有一篇很棒的文章“ A tour of V8: Garbage Collection ”解释了 V8 堆是如何组织的:
New-space: Most objects are allocated here. New-space is small and is
designed to be garbage collected very quickly, independent of other
spaces.
Old-pointer-space: Contains most objects which may have pointers to
other objects. Most objects are moved here after surviving in new-space
for a while.
Old-data-space: Contains objects which just contain raw data (no
pointers to other objects). Strings, boxed numbers, and arrays of
unboxed doubles are moved here after surviving in new-space for a
while.
Large-object-space: This space contains objects which are larger than
the size limits of other spaces. Each object gets its own mmap'd region
of memory. Large objects are never moved by the garbage collector.
Code-space: Code objects, which contain JITed instructions, are
allocated here. This is the only space with executable memory (although
Codes may be allocated in large-object-space, and those are executable, too).
Cell-space, property-cell-space and map-space: These spaces contain
Cells, PropertyCells, and Maps, respectively. Each of these spaces
contains objects which are all the same size and has some constraints
on what kind of objects they point to, which simplifies collection.
Conrad 的文章继续解释 V8 GC 是基于切尼算法的风格构建的。
V8 的堆实现位于heap.cc和heap.h中。堆的初始化从 开始line 5423
。在heap.hAddress NewSpaceStart()
中找到line 615
的方法包含新空间开始的地址位置,并且利用时间局部性将对象存储在哪里。
现在回答你的第二个问题:JVM 也这样做吗?一个有趣的事实:有 3 个主要的生产 JVM,它们都以不同的方式实现它们的 GC 算法。有一篇很棒的性能博客写了一篇文章“垃圾收集在三大 JVM 中有何不同”,它将更详细地讨论它们的实现。
还有一些 GC 风格,例如如果您想要一个低延迟环境,如果您在 Scala 中重新编写 JVM,以及.NET 环境中的延迟调整选项。
请让我知道,如果你有任何问题!
感谢您的时间,
温暖的问候,