summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2025-08-08 15:04:48 -0400
committerPeter Zhu <peter@peterzhu.ca>2025-08-08 16:04:11 -0400
commite639e5fd1af51e2462879d6db862ee5320914ba7 (patch)
treeecbc46850de700a7eada3cbe56b38b1bd853d630
parent0ba488d7f51c8b52811445245c87cb824e564069 (diff)
Make rb_gc_impl_writebarrier_remember Ractor-safe
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 <luke.gruber@shopify.com> Co-Authored-By: John Hawthorn <john@hawthorn.email>
-rw-r--r--gc/default/default.c20
1 files 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);
}
}