From e639e5fd1af51e2462879d6db862ee5320914ba7 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 8 Aug 2025 15:04:48 -0400 Subject: [PATCH] Make rb_gc_impl_writebarrier_remember Ractor-safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rb_gc_impl_writebarrier_remember is not Ractor safe because it writes to bitmaps and also pushes onto the mark stack during incremental marking. We should acquire the VM lock to prevent race conditions. In the case that the object is not old, there is no performance impact. However, we can see a performance impact in this microbenchmark where the object is old: 4.times.map do Ractor.new do ary = [] 3.times { GC.start } 10_000_000.times do |i| ary.push(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17) ary.clear end end end.map(&:value) Before: Time (mean ± σ): 682.4 ms ± 5.1 ms [User: 2564.8 ms, System: 16.0 ms] After: Time (mean ± σ): 5.522 s ± 0.096 s [User: 8.237 s, System: 7.931 s] Co-Authored-By: Luke Gruber Co-Authored-By: John Hawthorn --- gc/default/default.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/gc/default/default.c b/gc/default/default.c index 9038a01e4e..d4e34b9d03 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -6110,15 +6110,19 @@ rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj) gc_report(1, objspace, "rb_gc_writebarrier_remember: %s\n", rb_obj_info(obj)); - if (is_incremental_marking(objspace)) { - if (RVALUE_BLACK_P(objspace, obj)) { - gc_grey(objspace, obj); - } - } - else { - if (RVALUE_OLD_P(objspace, obj)) { - rgengc_remember(objspace, obj); + if (is_incremental_marking(objspace) || RVALUE_OLD_P(objspace, obj)) { + int lev = RB_GC_VM_LOCK_NO_BARRIER(); + { + if (is_incremental_marking(objspace)) { + if (RVALUE_BLACK_P(objspace, obj)) { + gc_grey(objspace, obj); + } + } + else if (RVALUE_OLD_P(objspace, obj)) { + rgengc_remember(objspace, obj); + } } + RB_GC_VM_UNLOCK_NO_BARRIER(lev); } }