From 4cc56592932d36c202b2366ffe7ad71db2f5ea0b Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 1 Sep 2023 10:07:32 -0400 Subject: [PATCH] Keep write-barrier status after splicing array We don't need to remove the write-barrier protected status after splicing an array. We can simply add it to the rememberset for marking during the next GC. The benchmark illustrates the performance impact on minor GC: ``` require "benchmark" arys = 1_000_000.times.map do ary = Array.new(50) ary.insert(1, 3) ary end 4.times { GC.start } puts(Benchmark.measure do 1000.times do GC.start(full_mark: false) end end) ``` This branch: ``` 1.309910 0.004342 1.314252 ( 1.314580) ``` Master branch: ``` 54.376091 0.219037 54.595128 ( 54.742996) ``` --- array.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/array.c b/array.c index 65041c9365..1032696308 100644 --- a/array.c +++ b/array.c @@ -2176,9 +2176,14 @@ rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen) ARY_SET_LEN(ary, alen); } if (rlen > 0) { - if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs; - /* give up wb-protected ary */ - RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary); + if (rofs == -1) { + rb_gc_writebarrier_remember(ary); + } + else { + /* In this case, we're copying from a region in this array, so + * we don't need to fire the write barrier. */ + rptr = RARRAY_CONST_PTR(ary) + rofs; + } /* do not use RARRAY_PTR() because it can causes GC. * ary can contain T_NONE object because it is not cleared.