Skip to content

Commit e6f73fc

Browse files
Remove HEAP_PAGE_OBJ_LIMIT
This was useful when there was only a single size pool to have an easy way of referencing the average number of objects a page could hold (this would vary by a few in real terms because of page alignment). But with multiple heaps, each heap contains pages with different numbers of objects because slot sizes are different. So when we use HEAP_PAGE_OBJ_LIMIT to do any kind of calculations: such as calculating freeable pages), then we're significantly underestimating the number of freeable pages in the larger size pools, which will cause us to hold on to pages unnecessarily. This commit replaces uses of HEAP_PAGE_OBJ_LIMIT with a more accurate approximation for the actual heap being manipulated. It also removes HEAP_PAGE_OBJ_LIMIT from GC::INTERNAL_CONSTANTS
1 parent 7ca0aa5 commit e6f73fc

2 files changed

Lines changed: 10 additions & 6 deletions

File tree

gc/default/default.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ typedef struct rb_heap_struct {
472472
uintptr_t compact_cursor_index;
473473
struct heap_page *pooled_pages;
474474
size_t total_pages; /* total page count in a heap */
475-
size_t total_slots; /* total slot count (about total_pages * HEAP_PAGE_OBJ_LIMIT) */
475+
size_t total_slots; /* total slot count */
476476

477477
} rb_heap_t;
478478

@@ -592,6 +592,7 @@ typedef struct rb_objspace {
592592
double gc_sweep_start_time;
593593
size_t total_allocated_objects_at_gc_start;
594594
size_t heap_used_at_gc_start;
595+
size_t heap_total_slots_at_gc_start;
595596

596597
/* basic statistics */
597598
size_t count;
@@ -700,7 +701,6 @@ enum {
700701
HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG),
701702
HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)),
702703
HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN,
703-
HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)) / BASE_SLOT_SIZE),
704704
HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, BASE_SLOT_SIZE), BITS_BITLENGTH),
705705
HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT),
706706
};
@@ -5454,8 +5454,13 @@ gc_marks_finish(rb_objspace_t *objspace)
54545454
max_free_slots = total_init_slots;
54555455
}
54565456

5457+
/* Approximate freeable pages using the average slots-per-pages across all heaps */
54575458
if (sweep_slots > max_free_slots) {
5458-
heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT;
5459+
size_t excess_slots = sweep_slots - max_free_slots;
5460+
size_t total_heap_pages = heap_eden_total_pages(objspace);
5461+
heap_pages_freeable_pages = total_heap_pages > 0
5462+
? excess_slots * total_heap_pages / total_slots
5463+
: 0;
54595464
}
54605465
else {
54615466
heap_pages_freeable_pages = 0;
@@ -6500,6 +6505,7 @@ gc_start(rb_objspace_t *objspace, unsigned int reason)
65006505
objspace->profile.latest_gc_info = reason;
65016506
objspace->profile.total_allocated_objects_at_gc_start = total_allocated_objects(objspace);
65026507
objspace->profile.heap_used_at_gc_start = rb_darray_size(objspace->heap_pages.sorted);
6508+
objspace->profile.heap_total_slots_at_gc_start = objspace_available_slots(objspace);
65036509
objspace->profile.weak_references_count = 0;
65046510
gc_prof_setup_new_record(objspace, reason);
65056511
gc_reset_malloc_info(objspace, do_full_mark);
@@ -8655,7 +8661,7 @@ gc_prof_set_heap_info(rb_objspace_t *objspace)
86558661
if (gc_prof_enabled(objspace)) {
86568662
gc_profile_record *record = gc_prof_record(objspace);
86578663
size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace);
8658-
size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT;
8664+
size_t total = objspace->profile.heap_total_slots_at_gc_start;
86598665

86608666
#if GC_PROFILE_MORE_DETAIL
86618667
record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
@@ -9551,7 +9557,6 @@ rb_gc_impl_init(void)
95519557
rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD));
95529558
rb_hash_aset(gc_constants, ID2SYM(rb_intern("RBASIC_SIZE")), SIZET2NUM(sizeof(struct RBasic)));
95539559
rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD));
9554-
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT));
95559560
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE));
95569561
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE));
95579562
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_COUNT")), LONG2FIX(HEAP_COUNT));

test/ruby/test_gc.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,6 @@ def allocate_large_object = Array.new(10)
694694
end
695695

696696
def test_gc_internals
697-
assert_not_nil GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT]
698697
assert_not_nil GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
699698
end
700699

0 commit comments

Comments
 (0)