一句话:提出 Mark–Scavenge 并发 GC 技术,通过延迟搬迁年轻代中稀疏存活对象,减少大量搬迁工作并在 ZGC 上验证。
移动式垃圾回收器通常通过疏散存活对象来释放连续内存:scavenging 在追踪时搬迁,适合年轻代但在稀疏区域工作少、内存开销大;mark–evacuate 在标记后搬迁,适合老年代且内存开销小,但并发 GC 中需等待搬迁完成才能回收。论文提出 mark–scavenge:观察到并发 GC 真正搬迁年轻对象时它们很可能已不可达,因而延迟搬迁,仅搬迁上一轮 GC 后仍存活且有利可图的稀疏对象簇,把并发 GC 为保证安全而预留的 headroom 转化为消除搬迁工作的资源。作者在 OpenJDK ZGC 上实现 MS-ZGC,并与 ZGC 对比。评估显示,根据机器相关因素,死对象搬迁最多减少 91%,表明该方法能显著削减 GC 的搬迁开销。
Moving garbage collectors (GCs) typically free memory by evacuating live objects in order to reclaim contiguous memory regions. Evacuation is typically done either during tracing (scavenging), or after tracing when identification of live objects is complete (mark–evacuate). Scavenging typically requires more memory (memory for all objects to be moved), but performs less work in sparse memory areas (single pass). This makes it attractive for collecting young objects. Mark–evacuate typically requires less memory and performs less work in memory areas with dense object clusters, by focusing relocation around sparse regions, making it attractive for collecting old objects. Mark–evacuate also completes identification of live objects faster, making it attractive for concurrent GCs that can reclaim memory immediately after identification of live objects finishes (as opposed to when evacuation finishes), at the expense of more work compared to scavenging, for young objects. We propose an alternative approach for concurrent GCs to combine the benefits of scavenging with the benefits of mark–evacuate, for young objects. The approach is based on the observation that by the time young objects are relocated by a concurrent GC, they are likely to already be unreachable. By performing relocation lazily, most of the relocations in the defragmentation phase of mark–evacuate can typically be eliminated. Similar to scavenging, objects are relocated during tracing with the proposed approach. However, instead of relocating all objects that are live in the current GC cycle, it lazily relocates profitable sparse object clusters that survived from the previous GC cycle. This turns the memory headroom that concurrent GCs typically “waste” in order to safely avoid running out of memory before GC finishes, into an asset used to eliminate much of the relocation work, which constitutes a significant portion of the GC work. We call this technique mark–scavenge and implement it on-top of ZGC in OpenJDK in a collector we call MS-ZGC. We perform a performance evaluation that compares MS-ZGC against ZGC. The most striking result is (up to) 91% reduction in relocation of dead objects (depending on machine-dependent factors).
@article{NorlinderOBW24,
title = {Mark–Scavenge: Waiting for Trash to Take Itself Out},
author = {Jonas Norlinder and Erik Österlund and David Black-Schaffer and Tobias Wrigstad},
journal = {Proceedings of the ACM on Programming Languages},
volume = {8},
number = {OOPSLA2},
year = {2024},
doi = {10.1145/3689791}
}