Bug #9607 » gc.patch
gc.c (working copy) | ||
---|---|---|
#define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
|
||
#endif
|
||
|
||
#ifndef GC_HEAP_FREE_SLOTS_MIN_RATIO
|
||
#define GC_HEAP_FREE_SLOTS_MIN_RATIO 0.3
|
||
#endif
|
||
#ifndef GC_HEAP_FREE_SLOTS_MAX_RATIO
|
||
#define GC_HEAP_FREE_SLOTS_MAX_RATIO 0.8
|
||
#endif
|
||
|
||
#ifndef GC_MALLOC_LIMIT_MIN
|
||
#define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
|
||
#endif
|
||
... | ... | |
heap_pages_increment = 0;
|
||
}
|
||
|
||
static void
|
||
heap_set_increment(rb_objspace_t *objspace, size_t minimum_limit)
|
||
static size_t
|
||
heap_extend_pages(rb_objspace_t *objspace)
|
||
{
|
||
size_t used = heap_pages_used - heap_tomb->page_length;
|
||
size_t next_used_limit = (size_t)(used * gc_params.growth_factor);
|
||
|
||
if (gc_params.growth_max_slots > 0) {
|
||
size_t max_used_limit = (size_t)(used + gc_params.growth_max_slots/HEAP_OBJ_LIMIT);
|
||
if (next_used_limit > max_used_limit) next_used_limit = max_used_limit;
|
||
}
|
||
|
||
return next_used_limit - used;
|
||
}
|
||
|
||
static void
|
||
heap_set_increment(rb_objspace_t *objspace, size_t additional_pages)
|
||
{
|
||
size_t used = heap_pages_used - heap_tomb->page_length;
|
||
size_t next_used_limit = used + additional_pages;
|
||
|
||
if (next_used_limit == heap_pages_used) next_used_limit++;
|
||
|
||
if (next_used_limit < minimum_limit) {
|
||
next_used_limit = minimum_limit;
|
||
}
|
||
|
||
heap_pages_increment = next_used_limit - used;
|
||
heap_pages_expand_sorted(objspace);
|
||
|
||
if (0) fprintf(stderr, "heap_set_increment: heap_pages_length: %d, heap_pages_used: %d, heap_pages_increment: %d, next_used_limit: %d\n",
|
||
(int)heap_pages_length, (int)heap_pages_used, (int)heap_pages_increment, (int)next_used_limit);
|
||
}
|
||
|
||
static int
|
||
... | ... | |
rgengc_report(1, objspace, "page_sweep: end.\n");
|
||
}
|
||
|
||
/* allocate additional minimum page to work */
|
||
/* allocate minimum page to work */
|
||
static void
|
||
gc_heap_allocate_minimum_page(rb_objspace_t *objspace, rb_heap_t *heap)
|
||
{
|
||
heap_set_increment(objspace, 1);
|
||
if (!heap_increment(objspace, heap)) { /* can't allocate additional free objects */
|
||
during_gc = 0;
|
||
rb_memerror();
|
||
}
|
||
}
|
||
|
||
static void
|
||
gc_heap_prepare_minimum_pages(rb_objspace_t *objspace, rb_heap_t *heap)
|
||
{
|
||
if (!heap->free_pages) {
|
||
/* there is no free after page_sweep() */
|
||
heap_set_increment(objspace, 0);
|
||
if (!heap_increment(objspace, heap)) { /* can't allocate additional free objects */
|
||
during_gc = 0;
|
||
rb_memerror();
|
||
#if USE_RGENGC
|
||
if (objspace->rgengc.during_minor_gc) {
|
||
/* do full GC */
|
||
garbage_collect(objspace, TRUE, TRUE, GPR_FLAG_NEWOBJ | GPR_FLAG_MAJOR_BY_NOFREE);
|
||
}
|
||
else {
|
||
gc_heap_allocate_minimum_page(objspace, heap);
|
||
}
|
||
#else
|
||
gc_heap_allocate_minimum_page(objspace, heap);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
... | ... | |
heap_pages_swept_slots = 0;
|
||
total_limit_slot = objspace_total_slot(objspace);
|
||
|
||
heap_pages_min_free_slots = (size_t)(total_limit_slot * 0.30);
|
||
heap_pages_min_free_slots = (size_t)(total_limit_slot * GC_HEAP_FREE_SLOTS_MIN_RATIO);
|
||
if (heap_pages_min_free_slots < gc_params.heap_free_slots) {
|
||
heap_pages_min_free_slots = gc_params.heap_free_slots;
|
||
}
|
||
heap_pages_max_free_slots = (size_t)(total_limit_slot * 0.80);
|
||
heap_pages_max_free_slots = (size_t)(total_limit_slot * GC_HEAP_FREE_SLOTS_MAX_RATIO);
|
||
if (heap_pages_max_free_slots < gc_params.heap_init_slots) {
|
||
heap_pages_max_free_slots = gc_params.heap_init_slots;
|
||
}
|
||
... | ... | |
static void
|
||
gc_after_sweep(rb_objspace_t *objspace)
|
||
{
|
||
rb_heap_t *heap = heap_eden;
|
||
/* extend heap when space is not enough */
|
||
#if USE_RGENGC
|
||
if (objspace->rgengc.during_minor_gc) {
|
||
if (heap_pages_swept_slots < heap_pages_min_free_slots) {
|
||
objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_RESCAN;
|
||
}
|
||
}
|
||
else {
|
||
/* check slots for newobj */
|
||
if (heap_pages_swept_slots < heap_pages_min_free_slots) {
|
||
/* do not have enough slots for new objects */
|
||
heap_set_increment(objspace, heap_extend_pages(objspace));
|
||
}
|
||
else if (gc_params.oldobject_limit_factor > 1) {
|
||
size_t old_object_count = objspace->rgengc.old_object_count;
|
||
size_t old_object_max = (size_t)(objspace->rgengc.old_object_limit * (1 - GC_HEAP_FREE_SLOTS_MIN_RATIO));
|
||
|
||
rgengc_report(1, objspace, "after_gc_sweep: heap->total_slots: %d, heap->swept_slots: %d, min_free_slots: %d\n",
|
||
(int)heap->total_slots, (int)heap_pages_swept_slots, (int)heap_pages_min_free_slots);
|
||
if (old_object_count > old_object_max) {
|
||
/* not enough old object space */
|
||
heap_set_increment(objspace, (old_object_count - old_object_max) / HEAP_OBJ_LIMIT + 1);
|
||
}
|
||
}
|
||
|
||
if (heap_pages_swept_slots < heap_pages_min_free_slots) {
|
||
heap_set_increment(objspace, (heap_pages_min_free_slots - heap_pages_swept_slots) / HEAP_OBJ_LIMIT);
|
||
heap_increment(objspace, heap);
|
||
/* setup old_object_limit & remembered_shady_object_limit */
|
||
{
|
||
/* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
|
||
size_t old_object_count = objspace->rgengc.old_object_count;
|
||
size_t old_limit_by_total_slots = (size_t)(objspace_total_slot(objspace) * (1 - GC_HEAP_FREE_SLOTS_MIN_RATIO));
|
||
const double r = gc_params.oldobject_limit_factor;
|
||
size_t old_limit_by_old_num = (size_t)(old_object_count * r);
|
||
|
||
#if USE_RGENGC
|
||
if (objspace->rgengc.remembered_shady_object_count + objspace->rgengc.old_object_count > (heap_pages_length * HEAP_OBJ_LIMIT) / 2) {
|
||
/* if [old]+[remembered shady] > [all object count]/2, then do major GC */
|
||
objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_RESCAN;
|
||
objspace->rgengc.old_object_limit =
|
||
old_limit_by_total_slots > old_limit_by_old_num ?
|
||
old_limit_by_old_num : old_limit_by_total_slots;
|
||
|
||
/* should we merge remembered shady object limit? */
|
||
objspace->rgengc.remembered_shady_object_limit = (size_t)(objspace->rgengc.remembered_shady_object_count * r);
|
||
}
|
||
}
|
||
#else
|
||
if (heap_pages_swept_slots < heap_pages_min_free_slots) {
|
||
/* do not have enough slots for new objects */
|
||
heap_set_increment(objspace, heap_extend_pages(objspace));
|
||
}
|
||
#endif
|
||
}
|
||
|
||
gc_prof_set_heap_info(objspace);
|
||
|
||
... | ... | |
}
|
||
gc_heap_lazy_sweep(objspace, heap_eden);
|
||
}
|
||
|
||
gc_heap_prepare_minimum_pages(objspace, heap_eden);
|
||
}
|
||
|
||
/* Marking - Marking stack */
|
||
... | ... | |
#endif
|
||
|
||
gc_marks_body(objspace, TRUE);
|
||
{
|
||
/* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
|
||
const double r = gc_params.oldobject_limit_factor;
|
||
objspace->rgengc.remembered_shady_object_limit = (size_t)(objspace->rgengc.remembered_shady_object_count * r);
|
||
objspace->rgengc.old_object_limit = (size_t)(objspace->rgengc.old_object_count * r);
|
||
}
|
||
}
|
||
else { /* minor GC */
|
||
gc_marks_body(objspace, FALSE);
|
||
... | ... | |
}
|
||
gc_prof_timer_stop(objspace);
|
||
|
||
gc_heap_prepare_minimum_pages(objspace, heap_eden);
|
||
|
||
if (GC_NOTIFY) fprintf(stderr, "end garbage_collect()\n");
|
||
return TRUE;
|
||
}
|
||
... | ... | |
if (dont_gc || during_gc) {
|
||
if (!heap->freelist && !heap->free_pages) {
|
||
if (!heap_increment(objspace, heap)) {
|
||
heap_set_increment(objspace, 0);
|
||
heap_set_increment(objspace, 1);
|
||
heap_increment(objspace, heap);
|
||
}
|
||
}
|