ruby-changes:30993
From: ko1 <ko1@a...>
Date: Fri, 27 Sep 2013 18:36:54 +0900 (JST)
Subject: [ruby-changes:30993] ko1:r43072 (trunk): * gc.c: add two GC tuning environment variables.
ko1 2013-09-27 18:36:48 +0900 (Fri, 27 Sep 2013) New Revision: 43072 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43072 Log: * gc.c: add two GC tuning environment variables. RUBY_GC_MALLOC_LIMIT_MAX and RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR. See r43067 for details. * gc.c (rb_gc_set_params): refactoring. And change verbose notation. Mostly duplicated functions get_envparam_int/double is not cool. Please rewrite it. * test/ruby/test_gc.rb: fix a test for this change. Modified files: trunk/ChangeLog trunk/gc.c trunk/test/ruby/test_gc.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 43071) +++ ChangeLog (revision 43072) @@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Sep 27 18:33:23 2013 Koichi Sasada <ko1@a...> + + * gc.c: add two GC tuning environment variables. + RUBY_GC_MALLOC_LIMIT_MAX and RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR. + See r43067 for details. + + * gc.c (rb_gc_set_params): refactoring. And change verbose notation. + Mostly duplicated functions get_envparam_int/double is not cool. + Please rewrite it. + + * test/ruby/test_gc.rb: fix a test for this change. + Fri Sep 27 17:44:41 2013 Koichi Sasada <ko1@a...> * gc.c (GC_MALLOC_LIMIT): 8,000,000 -> 8 * 1,024 * 1,024. Index: gc.c =================================================================== --- gc.c (revision 43071) +++ gc.c (revision 43072) @@ -92,8 +92,8 @@ rb_gc_guarded_ptr(volatile VALUE *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L92 #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 +#ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR +#define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.8 #endif typedef struct { @@ -102,7 +102,7 @@ typedef struct { https://github.com/ruby/ruby/blob/trunk/gc.c#L102 double initial_growth_factor; unsigned int initial_malloc_limit; unsigned int initial_malloc_limit_max; - double initial_malloc_limit_factor; + double initial_malloc_limit_growth_factor; #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE VALUE gc_stress; #endif @@ -114,7 +114,7 @@ static ruby_gc_params_t initial_params = https://github.com/ruby/ruby/blob/trunk/gc.c#L114 GC_HEAP_GROWTH_FACTOR, GC_MALLOC_LIMIT, GC_MALLOC_LIMIT_MAX, - GC_MALLOC_LIMIT_FACTOR, + GC_MALLOC_LIMIT_GROWTH_FACTOR, #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE FALSE, #endif @@ -503,14 +503,16 @@ 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_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 +#define initial_malloc_limit initial_params.initial_malloc_limit +#define initial_malloc_limit_max initial_params.initial_malloc_limit_max +#define initial_malloc_limit_growth_factor initial_params.initial_malloc_limit_growth_factor +#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 is_lazy_sweeping(objspace) ((objspace)->heap.sweep_slots != 0) #if SIZEOF_LONG == SIZEOF_VOIDP @@ -2405,13 +2407,13 @@ gc_before_sweep(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L2407 size_t old_limit = malloc_limit; if (inc > malloc_limit) { - malloc_limit += (size_t)(malloc_limit * (initial_params.initial_malloc_limit_factor - 1)); + malloc_limit += (size_t)(malloc_limit * (initial_malloc_limit_growth_factor - 1)); if (malloc_limit > initial_malloc_limit_max) { malloc_limit = initial_malloc_limit_max; } } else { - malloc_limit -= (size_t)(malloc_limit * ((initial_params.initial_malloc_limit_factor - 1) / 4)); + malloc_limit -= (size_t)(malloc_limit * ((initial_malloc_limit_growth_factor - 1) / 4)); if (malloc_limit < initial_malloc_limit) { malloc_limit = initial_malloc_limit; } @@ -4600,63 +4602,67 @@ rb_gc_disable(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L4602 return old ? Qtrue : Qfalse; } -void -rb_gc_set_params(void) +static int +get_envparam_int(const char *name, unsigned int *default_value, int lower_bound) { - char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr, *growth_factor_ptr; + char *ptr = getenv(name); + int val; - if (rb_safe_level() > 0) return; - - malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT"); - if (malloc_limit_ptr != NULL) { - int malloc_limit_i = atoi(malloc_limit_ptr); - if (RTEST(ruby_verbose)) - fprintf(stderr, "malloc_limit=%d (%d)\n", - malloc_limit_i, initial_malloc_limit); - if (malloc_limit_i > 0) { - initial_malloc_limit = malloc_limit_i; + if (ptr != NULL) { + val = atoi(ptr); + if (val > lower_bound) { + if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%d (%d)\n", name, val, *default_value); + *default_value = val; + return 1; + } + else { + if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%d (%d), but ignored because lower than %d\n", name, val, *default_value, lower_bound); } } + return 0; +} - heap_min_slots_ptr = getenv("RUBY_HEAP_MIN_SLOTS"); - if (heap_min_slots_ptr != NULL) { - int heap_min_slots_i = atoi(heap_min_slots_ptr); - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_min_slots=%d (%d)\n", - heap_min_slots_i, initial_heap_min_slots); - if (heap_min_slots_i > 0) { - size_t min_size; - rb_objspace_t *objspace = &rb_objspace; - - initial_heap_min_slots = heap_min_slots_i; - min_size = initial_heap_min_slots / HEAP_OBJ_LIMIT; +static int +get_envparam_double(const char *name, double *default_value, double lower_bound) +{ + char *ptr = getenv(name); + double val; - if (min_size > heap_used) { - heap_add_slots(objspace, min_size - heap_used); - } + if (ptr != NULL) { + val = strtod(ptr, NULL); + if (val > lower_bound) { + if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (%f)\n", name, val, *default_value); + *default_value = val; + return 1; } - } - - growth_factor_ptr = getenv("RUBY_HEAP_SLOTS_GROWTH_FACTOR"); - if (growth_factor_ptr != NULL) { - double growth_factor_f = strtod(growth_factor_ptr, NULL); - if (RTEST(ruby_verbose)) - fprintf(stderr, "heap_slots_growth_factor=%f (%f)\n", - growth_factor_f, initial_growth_factor); - if (growth_factor_f > 1) { - initial_growth_factor = growth_factor_f; + else { + if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (%f), but ignored because lower than %f\n", name, val, *default_value, lower_bound); } } + return 0; +} - free_min_ptr = getenv("RUBY_FREE_MIN"); - if (free_min_ptr != NULL) { - int free_min_i = atoi(free_min_ptr); - if (RTEST(ruby_verbose)) - fprintf(stderr, "free_min=%d (%d)\n", free_min_i, initial_free_min); - if (free_min_i > 0) { - initial_free_min = free_min_i; +void +rb_gc_set_params(void) +{ + if (rb_safe_level() > 0) return; + + get_envparam_int ("RUBY_FREE_MIN", &initial_free_min, 0); + + get_envparam_double("RUBY_HEAP_SLOTS_GROWTH_FACTOR", &initial_growth_factor, 1.0); + if (get_envparam_int("RUBY_HEAP_MIN_SLOTS", &initial_heap_min_slots, 0)) { + size_t min_size; + rb_objspace_t *objspace = &rb_objspace; + + min_size = initial_heap_min_slots / HEAP_OBJ_LIMIT; + if (min_size > heap_used) { + heap_add_slots(objspace, min_size - heap_used); } } + + get_envparam_int ("RUBY_GC_MALLOC_LIMIT", &initial_malloc_limit, 0); + get_envparam_int ("RUBY_GC_MALLOC_LIMIT_MAX", &initial_malloc_limit_max, initial_malloc_limit); + get_envparam_double("RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR", &initial_malloc_limit_growth_factor, 1.0); } void Index: test/ruby/test_gc.rb =================================================================== --- test/ruby/test_gc.rb (revision 43071) +++ test/ruby/test_gc.rb (revision 43072) @@ -113,13 +113,23 @@ class TestGc < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_gc.rb#L113 assert_in_out_err([env, "-e", "exit"], "", [], [], "[ruby-core:39795]") assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [], "[ruby-core:39795]") assert_in_out_err([env, "-W1", "-e", "exit"], "", [], [], "[ruby-core:39795]") - assert_in_out_err([env, "-w", "-e", "exit"], "", [], /heap_min_slots=100000/, "[ruby-core:39795]") + assert_in_out_err([env, "-w", "-e", "exit"], "", [], /HEAP_MIN_SLOTS=100000/, "[ruby-core:39795]") env = { "RUBY_HEAP_SLOTS_GROWTH_FACTOR" => "2.0" } assert_normal_exit("exit", "", :child_env => env) - assert_in_out_err([env, "-w", "-e", "exit"], "", [], /heap_slots_growth_factor=2.0/, "") + assert_in_out_err([env, "-w", "-e", "exit"], "", [], /HEAP_SLOTS_GROWTH_FACTOR=2.0/, "") + + env = { + "RUBY_GC_MALLOC_LIMIT" => "60000000", + "RUBY_GC_MALLOC_LIMIT_MAX" => "160000000", + "RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR" => "2.0" + } + assert_normal_exit("exit", "", :child_env => env) + assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_MALLOC_LIMIT=6000000/, "") + assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_MALLOC_LIMIT_MAX=16000000/, "") + assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR=2.0/, "") end def test_profiler_enabled -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/