From 9ebef81e2c75628f07fde169937824376be71351 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 23 Feb 2026 18:18:44 +0900 Subject: [PATCH 1/2] Relax thresholds for compaction verification These tests failed with RHEL10 again. --- test/ruby/test_gc_compact.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index 7e0c499dd9c82c..f3da8e4e138432 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -300,7 +300,7 @@ def test_moving_arrays_down_heaps }.resume stats = GC.verify_compaction_references(expand_heap: true, toward: :empty) - assert_operator(stats.dig(:moved_down, :T_ARRAY) || 0, :>=, ARY_COUNT - 10) + assert_operator(stats.dig(:moved_down, :T_ARRAY) || 0, :>=, ARY_COUNT - 25) refute_empty($arys.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') }) end; end @@ -356,7 +356,7 @@ def add_ivars stats = GC.verify_compaction_references(expand_heap: true, toward: :empty) - assert_operator(stats.dig(:moved_up, :T_OBJECT) || 0, :>=, OBJ_COUNT - 15) + assert_operator(stats.dig(:moved_up, :T_OBJECT) || 0, :>=, OBJ_COUNT - 25) refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') }) end; end @@ -393,7 +393,7 @@ def test_moving_strings_up_heaps stats = GC.verify_compaction_references(expand_heap: true, toward: :empty) - assert_operator(stats[:moved_up][:T_STRING], :>=, STR_COUNT - 15) + assert_operator(stats[:moved_up][:T_STRING], :>=, STR_COUNT - 25) refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') }) end; end @@ -413,7 +413,7 @@ def test_moving_strings_down_heaps stats = GC.verify_compaction_references(expand_heap: true, toward: :empty) - assert_operator(stats[:moved_down][:T_STRING], :>=, STR_COUNT - 10) + assert_operator(stats[:moved_down][:T_STRING], :>=, STR_COUNT - 25) refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') }) end; end @@ -437,7 +437,7 @@ def test_moving_hashes_down_heaps stats = GC.verify_compaction_references(expand_heap: true, toward: :empty) - assert_operator(stats[:moved_down][:T_HASH], :>=, HASH_COUNT - 10) + assert_operator(stats[:moved_down][:T_HASH], :>=, HASH_COUNT - 25) end; end From fd492edd4996f3481949509222224d038c4e3481 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Thu, 19 Feb 2026 19:12:32 +0000 Subject: [PATCH 2/2] Fix spurious uses of BASE_SLOT_SIZE In gc_sweep_plane, VALGRIND_MAKE_MEM_UNDEFINED was using BASE_SLOT_SIZE which only covers the smallest pool's slot size. For larger size pools this left the tail of the slot with stale state. Use the page's actual slot_size instead. In gc_prof_set_heap_info, heap_use_size and heap_total_size were computed as object_count * BASE_SLOT_SIZE, undercounting memory for objects in larger size pools. Sum across all heaps using each pool's actual slot size for correct byte totals. --- gc/default/default.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/gc/default/default.c b/gc/default/default.c index 9cb65da9023857..046aa146f73055 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -3546,7 +3546,7 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit rb_gc_event_hook(vp, RUBY_INTERNAL_EVENT_FREEOBJ); } - (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE); + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, slot_size); heap_page_add_freeobj(objspace, sweep_page, vp); gc_report(3, objspace, "page_sweep: %s (fast path) added to freelist\n", rb_obj_info(vp)); ctx->freed_slots++; @@ -3558,7 +3558,7 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit rb_gc_obj_free_vm_weak_references(vp); if (rb_gc_obj_free(objspace, vp)) { - (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE); + (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, slot_size); heap_page_add_freeobj(objspace, sweep_page, vp); gc_report(3, objspace, "page_sweep: %s is added to freelist\n", rb_obj_info(vp)); ctx->freed_slots++; @@ -8647,18 +8647,29 @@ gc_prof_set_heap_info(rb_objspace_t *objspace) { if (gc_prof_enabled(objspace)) { gc_profile_record *record = gc_prof_record(objspace); - size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace); - size_t total = objspace->profile.heap_total_slots_at_gc_start; + + /* Sum across all size pools since each has a different slot size. */ + size_t total = 0; + size_t use_size = 0; + size_t total_size = 0; + for (int i = 0; i < HEAP_COUNT; i++) { + rb_heap_t *heap = &heaps[i]; + size_t heap_live = heap->total_allocated_objects - heap->total_freed_objects - heap->final_slots_count; + total += heap->total_slots; + use_size += heap_live * heap->slot_size; + total_size += heap->total_slots * heap->slot_size; + } #if GC_PROFILE_MORE_DETAIL + size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace); record->heap_use_pages = objspace->profile.heap_used_at_gc_start; record->heap_live_objects = live; record->heap_free_objects = total - live; #endif record->heap_total_objects = total; - record->heap_use_size = live * BASE_SLOT_SIZE; - record->heap_total_size = total * BASE_SLOT_SIZE; + record->heap_use_size = use_size; + record->heap_total_size = total_size; } }