[前][次][番号順一覧][スレッド一覧]

ruby-changes:30988

From: ko1 <ko1@a...>
Date: Fri, 27 Sep 2013 17:01:21 +0900 (JST)
Subject: [ruby-changes:30988] ko1:r43067 (trunk): * gc.c: simplify threshold of GC caused by malloc_increase.

ko1	2013-09-27 17:01:14 +0900 (Fri, 27 Sep 2013)

  New Revision: 43067

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43067

  Log:
    * gc.c: simplify threshold of GC caused by malloc_increase.
      Now, malloc_limit is increased/decreased by mysterious logic.
      This fix simplify malloc_limit increase/decrease logic such as:
      if (malloc_increase > malloc_limit) /* so many malloc */
      malloc_limit += malloc_limit * (GC_MALLOC_LIMIT_FACTOR-1);
      else
      malloc_limit -= malloc_limit * (GC_MALLOC_LIMIT_FACTOR-1)/4;
      Default value of GC_MALLOC_LIMIT_FACTOR is 1.8.
      malloc_limit is bounded by GC_MALLOC_LIMIT_MAX (256MB by default).
      This logic runs at before_sweeep(). So there are no effect from
      caused by lazy sweep. And we can remove malloc_increase2.
    * gc.c (HEAP_MIN_SLOTS, FREE_MIN, HEAP_GROWTH_FACTOR): rename to
      GC_HEAP_MIN_SLOTS, GC_FREE_MIN, GC_HEAP_GROWTH_FACTOR respectively.
      Check them by `#ifndef' so you can specify these values outside gc.c.
    * gc.c (ruby_gc_params_t): add initial_malloc_limit_factor and
      initial_malloc_limit_max.
    * gc.c (vm_malloc_prepare, vm_xrealloc): use vm_malloc_increase to
      add and check malloc_increase.

  Modified files:
    trunk/ChangeLog
    trunk/gc.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43066)
+++ ChangeLog	(revision 43067)
@@ -1,3 +1,27 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Sep 27 16:32:27 2013  Koichi Sasada  <ko1@a...>
+
+	* gc.c: simplify threshold of GC caused by malloc_increase.
+	  Now, malloc_limit is increased/decreased by mysterious logic.
+	  This fix simplify malloc_limit increase/decrease logic such as:
+	    if (malloc_increase > malloc_limit) /* so many malloc */
+	      malloc_limit += malloc_limit * (GC_MALLOC_LIMIT_FACTOR-1);
+	    else
+	      malloc_limit -= malloc_limit * (GC_MALLOC_LIMIT_FACTOR-1)/4;
+	  Default value of GC_MALLOC_LIMIT_FACTOR is 1.8.
+	  malloc_limit is bounded by GC_MALLOC_LIMIT_MAX (256MB by default).
+	  This logic runs at before_sweeep(). So there are no effect from
+	  caused by lazy sweep. And we can remove malloc_increase2.
+
+	* gc.c (HEAP_MIN_SLOTS, FREE_MIN, HEAP_GROWTH_FACTOR): rename to
+	  GC_HEAP_MIN_SLOTS, GC_FREE_MIN, GC_HEAP_GROWTH_FACTOR respectively.
+	  Check them by `#ifndef' so you can specify these values outside gc.c.
+
+	* gc.c (ruby_gc_params_t): add initial_malloc_limit_factor and 
+	  initial_malloc_limit_max.
+
+	* gc.c (vm_malloc_prepare, vm_xrealloc): use vm_malloc_increase to
+	  add and check malloc_increase.
+
 Fri Sep 27 01:05:00 2013  Zachary Scott  <e@z...>
 
 	* re.c: [DOC] arguments of Regexp::union receive #to_regexp [Bug #8205]
Index: gc.c
===================================================================
--- gc.c	(revision 43066)
+++ gc.c	(revision 43067)
@@ -77,28 +77,44 @@ rb_gc_guarded_ptr(volatile VALUE *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L77
 }
 #endif
 
+#ifndef GC_FREE_MIN
+#define GC_FREE_MIN  4096
+#endif
+#ifndef GC_HEAP_MIN_SLOTS
+#define GC_HEAP_MIN_SLOTS 10000
+#endif
+#ifndef GC_HEAP_GROWTH_FACTOR
+#define GC_HEAP_GROWTH_FACTOR 1.8
+#endif
 #ifndef GC_MALLOC_LIMIT
 #define GC_MALLOC_LIMIT 8000000
 #endif
-#define HEAP_MIN_SLOTS 10000
-#define FREE_MIN  4096
-#define HEAP_GROWTH_FACTOR 1.8
+#ifndef GC_MALLOC_LIMIT_MAX
+#define GC_MALLOC_LIMIT_MAX (256 /* 256 MB */ * 1024 * 1024 /* 1MB */)
+#endif
+#ifndef GC_MALLOC_LIMIT_FACTOR
+#define GC_MALLOC_LIMIT_FACTOR 1.8
+#endif
 
 typedef struct {
-    unsigned int initial_malloc_limit;
     unsigned int initial_heap_min_slots;
     unsigned int initial_free_min;
     double initial_growth_factor;
+    unsigned int initial_malloc_limit;
+    unsigned int initial_malloc_limit_max;
+    double initial_malloc_limit_factor;
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     VALUE gc_stress;
 #endif
 } ruby_gc_params_t;
 
 static ruby_gc_params_t initial_params = {
+    GC_HEAP_MIN_SLOTS,
+    GC_FREE_MIN,
+    GC_HEAP_GROWTH_FACTOR,
     GC_MALLOC_LIMIT,
-    HEAP_MIN_SLOTS,
-    FREE_MIN,
-    HEAP_GROWTH_FACTOR,
+    GC_MALLOC_LIMIT_MAX,
+    GC_MALLOC_LIMIT_FACTOR,
 #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
     FALSE,
 #endif
@@ -302,7 +318,6 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L318
     struct {
 	size_t limit;
 	size_t increase;
-	size_t increase2;
 #if CALC_EXACT_MALLOC_SIZE
 	size_t allocated_size;
 	size_t allocations;
@@ -474,7 +489,6 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_ https://github.com/ruby/ruby/blob/trunk/gc.c#L489
 
 #define malloc_limit		objspace->malloc_params.limit
 #define malloc_increase 	objspace->malloc_params.increase
-#define malloc_increase2 	objspace->malloc_params.increase2
 #define malloc_allocated_size 	objspace->malloc_params.allocated_size
 #define heap_slots		objspace->heap.slots
 #define heap_length		objspace->heap.length
@@ -489,10 +503,11 @@ VALUE *ruby_initial_gc_stress_ptr = &rb_ https://github.com/ruby/ruby/blob/trunk/gc.c#L503
 #define deferred_final_list	objspace->final.deferred
 #define global_List		objspace->global_list
 #define ruby_gc_stress		objspace->gc_stress
-#define initial_malloc_limit	initial_params.initial_malloc_limit
-#define initial_heap_min_slots	initial_params.initial_heap_min_slots
-#define initial_free_min	initial_params.initial_free_min
-#define initial_growth_factor	initial_params.initial_growth_factor
+#define initial_malloc_limit	 initial_params.initial_malloc_limit
+#define initial_malloc_limit_max initial_params.initial_malloc_limit_max
+#define initial_heap_min_slots	 initial_params.initial_heap_min_slots
+#define initial_free_min	 initial_params.initial_free_min
+#define initial_growth_factor	 initial_params.initial_growth_factor
 #define monitor_level           objspace->rgengc.monitor_level
 #define monitored_object_table  objspace->rgengc.monitored_object_table
 
@@ -837,7 +852,7 @@ heap_add_slots(rb_objspace_t *objspace, https://github.com/ruby/ruby/blob/trunk/gc.c#L852
 static void
 heap_init(rb_objspace_t *objspace)
 {
-    heap_add_slots(objspace, HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT);
+    heap_add_slots(objspace, initial_heap_min_slots / HEAP_OBJ_LIMIT);
     init_mark_stack(&objspace->mark_stack);
 
 #ifdef USE_SIGALTSTACK
@@ -2362,9 +2377,10 @@ gc_before_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2377
     objspace->heap.do_heap_free = (size_t)((heap_used * HEAP_OBJ_LIMIT) * 0.65);
     objspace->heap.free_min = (size_t)((heap_used * HEAP_OBJ_LIMIT)  * 0.2);
     if (objspace->heap.free_min < initial_free_min) {
-        objspace->heap.free_min = initial_free_min;
-	if (objspace->heap.do_heap_free < initial_free_min)
+	objspace->heap.free_min = initial_free_min;
+	if (objspace->heap.do_heap_free < initial_free_min) {
 	    objspace->heap.do_heap_free = initial_free_min;
+	}
     }
     objspace->heap.sweep_slots = heap_slots;
     objspace->heap.free_num = 0;
@@ -2376,19 +2392,41 @@ gc_before_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2392
     }
     objspace->freelist = NULL;
 
-    ATOMIC_SIZE_ADD(malloc_increase2, ATOMIC_SIZE_EXCHANGE(malloc_increase, 0));
-
     /* sweep unlinked method entries */
     if (GET_VM()->unlinked_method_entry_list) {
 	rb_sweep_method_entry(GET_VM());
     }
+
+
+    gc_prof_set_malloc_info(objspace);
+
+    /* reset malloc info */
+    {
+	size_t inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
+	size_t old_limit = malloc_limit;
+
+	if (inc > malloc_limit) {
+	    malloc_limit += malloc_limit * (initial_params.initial_malloc_limit_factor - 1); /* 1 > factor */
+	    if (malloc_limit > initial_malloc_limit_max) {
+		malloc_limit = initial_malloc_limit_max;
+	    }
+	}
+	else {
+	    malloc_limit -= malloc_limit * ((initial_params.initial_malloc_limit_factor - 1) / 4);
+	    if (malloc_limit < initial_malloc_limit) {
+		malloc_limit = initial_malloc_limit;
+	    }
+	}
+
+	if (0) {
+	    fprintf(stderr, "malloc_limit: %zu -> %zu\n", old_limit, malloc_limit);
+	}
+    }
 }
 
 static void
 gc_after_sweep(rb_objspace_t *objspace)
 {
-    size_t inc;
-
     rgengc_report(1, objspace, "after_gc_sweep: objspace->heap.free_num: %d, objspace->heap.free_min: %d\n",
 		  objspace->heap.free_num, objspace->heap.free_min);
 
@@ -2404,18 +2442,8 @@ gc_after_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2442
 #endif
     }
 
-    gc_prof_set_malloc_info(objspace);
     gc_prof_set_heap_info(objspace);
 
-    inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
-    inc += ATOMIC_SIZE_EXCHANGE(malloc_increase2, 0);
-
-    if (inc > malloc_limit) {
-	malloc_limit +=
-	  (size_t)((inc - malloc_limit) * (double)objspace_live_num(objspace) / (heap_used * HEAP_OBJ_LIMIT));
-	if (malloc_limit < initial_malloc_limit) malloc_limit = initial_malloc_limit;
-    }
-
     free_unused_slots(objspace);
 
     gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END, 0 /* TODO: pass minor/immediate flag? */);
@@ -4682,6 +4710,17 @@ aligned_free(void *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L4710
 #endif
 }
 
+static void
+vm_malloc_increase(rb_objspace_t *objspace, size_t size)
+{
+    ATOMIC_SIZE_ADD(malloc_increase, size);
+
+    if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
+	malloc_increase > malloc_limit) {
+	garbage_collect_with_gvl(objspace, 0, 0, GPR_FLAG_MALLOC);
+    }
+}
+
 static inline size_t
 vm_malloc_prepare(rb_objspace_t *objspace, size_t size)
 {
@@ -4694,11 +4733,7 @@ vm_malloc_prepare(rb_objspace_t *objspac https://github.com/ruby/ruby/blob/trunk/gc.c#L4733
     size += sizeof(size_t);
 #endif
 
-    ATOMIC_SIZE_ADD(malloc_increase, size);
-    if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
-	malloc_increase > malloc_limit) {
-	garbage_collect_with_gvl(objspace, 0, 0, GPR_FLAG_MALLOC);
-    }
+    vm_malloc_increase(objspace, size);
 
     return size;
 }
@@ -4757,8 +4792,8 @@ vm_xrealloc(rb_objspace_t *objspace, voi https://github.com/ruby/ruby/blob/trunk/gc.c#L4792
 	vm_xfree(objspace, ptr);
 	return 0;
     }
-    if (ruby_gc_stress && !ruby_disable_gc_stress)
-	garbage_collect_with_gvl(objspace, 0, 0, GPR_FLAG_MALLOC);
+
+    vm_malloc_increase(objspace, size);
 
 #if CALC_EXACT_MALLOC_SIZE
     size += sizeof(size_t);
@@ -4767,7 +4802,6 @@ vm_xrealloc(rb_objspace_t *objspace, voi https://github.com/ruby/ruby/blob/trunk/gc.c#L4802
 #endif
 
     TRY_WITH_GC(mem = realloc(ptr, size));
-    ATOMIC_SIZE_ADD(malloc_increase, size);
 
 #if CALC_EXACT_MALLOC_SIZE
     ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, size - oldsize);
@@ -5276,7 +5310,7 @@ gc_prof_set_malloc_info(rb_objspace_t *o https://github.com/ruby/ruby/blob/trunk/gc.c#L5310
 #if GC_PROFILE_MORE_DETAIL
     if (objspace->profile.run) {
         gc_profile_record *record = gc_prof_record(objspace);
-	record->allocate_increase = malloc_increase + malloc_increase2;
+	record->allocate_increase = malloc_increase;
 	record->allocate_limit = malloc_limit;
     }
 #endif

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]