diff options
| author | Peter Zhu <peter@peterzhu.ca> | 2023-08-28 16:34:27 -0400 |
|---|---|---|
| committer | Peter Zhu <peter@peterzhu.ca> | 2023-08-28 18:01:29 -0400 |
| commit | fd0df1f8c6845671c86eddd85c9bcced30501690 (patch) | |
| tree | 5e402dc35fdbfe5b089f1dd55eaf2db21ca4ea3c /test/ruby | |
| parent | 5485680244bc40a9dba52e468fc5705973f2f5bd (diff) | |
Fix growth in minor GC when we have initial slots
If initial slots is set, then during a minor GC, if we have allocatable
pages but the heap is mostly full, then we will set `grow_heap` to true
since `total_slots` does not count allocatable pages so it will be less
than `init_slots`. This can cause `allocatable_pages` to grow to much
higher than desired since it will appear that the heap is mostly full.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8310
Diffstat (limited to 'test/ruby')
| -rw-r--r-- | test/ruby/test_gc.rb | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index c5a9731f8a..8fc511331e 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -492,6 +492,45 @@ class TestGc < Test::Unit::TestCase assert_in_epsilon(SIZES[i], total_slots, 0.01, s) end RUBY + + # Check that we don't grow the heap in minor GC if we have alloctable pages. + env["RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO"] = "0.3" + env["RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO"] = "0.99" + env["RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO"] = "1.0" + env["RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR"] = "100" # Large value to disable major GC + assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY) + SIZES = #{sizes} + + # Run a major GC to clear out dead objects. + GC.start + + # Disable GC so we can control when GC is ran. + GC.disable + + # Run minor GC enough times so that we don't grow the heap because we + # haven't yet ran RVALUE_OLD_AGE minor GC cycles. + GC::INTERNAL_CONSTANTS[:RVALUE_OLD_AGE].times { GC.start(full_mark: false) } + + # Fill size pool 0 to over 50% full so that the number of allocatable + # pages that will be created will be over the number in heap_allocatable_pages + # (calculated using RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO). + # 70% was chosen here to guarantee that. + ary = [] + while GC.stat_heap(0, :heap_allocatable_pages) > + (GC.stat_heap(0, :heap_allocatable_pages) + GC.stat_heap(0, :heap_eden_pages)) * 0.3 + ary << Object.new + end + + GC.start(full_mark: false) + + # Check that we still have the same number of slots as initially configured. + GC.stat_heap.each do |i, s| + # Sometimes pages will have 1 less slot due to alignment, so always increase slots_per_page by 1. + slots_per_page = (s[:heap_eden_slots] / s[:heap_eden_pages]) + 1 + total_slots = s[:heap_eden_slots] + s[:heap_allocatable_pages] * slots_per_page + assert_in_epsilon(SIZES[i], total_slots, 0.01, s) + end + RUBY end def test_profiler_enabled |
