Index: gc.c =================================================================== --- gc.c (revision 25630) +++ gc.c (working copy) @@ -296,6 +296,7 @@ struct { size_t limit; size_t increase; + size_t count; #if CALC_EXACT_MALLOC_SIZE size_t allocated_size; size_t allocations; @@ -345,6 +346,7 @@ #endif #define malloc_limit objspace->malloc_params.limit #define malloc_increase objspace->malloc_params.increase +#define malloc_count objspace->malloc_params.count #define heap_slots objspace->heap.slots #define heaps objspace->heap.ptr #define heaps_length objspace->heap.length @@ -664,6 +666,7 @@ } } malloc_increase += size; + malloc_count++; #if CALC_EXACT_MALLOC_SIZE objspace->malloc_params.allocated_size += size; @@ -679,6 +682,7 @@ vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size) { void *mem; + int increase_size; if ((ssize_t)size < 0) { negative_size_allocation_error("negative re-allocation size"); @@ -688,8 +692,16 @@ vm_xfree(objspace, ptr); return 0; } - if (ruby_gc_stress && !ruby_disable_gc_stress) + + increase_size = size - malloc_increase / (malloc_count + 1); + if (increase_size < 0) { + increase_size = 0; + } + + if ((ruby_gc_stress && !ruby_disable_gc_stress) || + (malloc_increase+increase_size) > malloc_limit) { garbage_collect_with_gvl(objspace); + } #if CALC_EXACT_MALLOC_SIZE size += sizeof(size_t); @@ -706,7 +718,7 @@ ruby_memerror(); } } - malloc_increase += size; + malloc_increase += increase_size; #if CALC_EXACT_MALLOC_SIZE objspace->malloc_params.allocated_size += size; @@ -1921,6 +1933,7 @@ if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT; } malloc_increase = 0; + malloc_count = 0; if (freed < free_min) { set_heaps_increment(objspace); heaps_increment(objspace);