Project

General

Profile

Bug #9607 » gc.patch

ko1 (Koichi Sasada), 03/07/2014 09:07 AM

View differences:

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);
}
}
(5-5/7)