Feature #18494
Updated by ko1 (Koichi Sasada) almost 3 years ago
This is intended to give Ruby application developers a way to to improve the out-of-the-box experience for end users running tools written in Ruby. In most cases, end users are not and cannot be expected to know how to tune the GC better than the developers who wrote the Ruby code. This has no extra API footprint, and will silently be a no-op for other Ruby implementations. One potential incompatibility is users doing something like: ENV["RUBY_GC_..."] = "1m" system(...) However, the different behavior would be largely innocuous aside from different performance characteristics in the parent process. Using: system({ "RUBY_GC_..." => "1m" }, ...) ...would restore the previous behavior (and is generally the preferred usage, anyways, to avoid thread-safety issues). RFC since I've only tested this with RUBY_GC_MALLOC_LIMIT and RUBY_GC_MALLOC_LIMIT_MAX, so far. I've yet to check Ractor interactions since haven't followed Ruby in several years. I made this change to reduce memory use in a single-threaded pipeline+process manager designed for audio playback; but it probably makes sense for many long-running daemons that want to clamp memory use after all code is loaded. --- Note: I can't create Redmine tickets due to MFA: [ruby-core:105878]. I completely disagree with MFA for Open Source contributions as it's a needless barrier to participation. Open Source worked fine for decades without MFA. I show you my code and even explain my changes; but nobody here knows me and nobody ever will. I don't want nor need anyone to trust me when they can read my code and even ask me to clarify things if needed. ```diff hash.c | 5 +++++ test/ruby/test_gc.rb | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/hash.c b/hash.c index f032ef642a..d7cc797ef5 100644 --- a/hash.c +++ b/hash.c @@ -4911,6 +4911,7 @@ static VALUE env_aset(VALUE nm, VALUE val); static void reset_by_modified_env(const char *nam) { + static char gc_var_pfx[] = "RUBY_GC_"; /* * ENV['TZ'] = nil has a special meaning. * TZ is no longer considered up-to-date and ruby call tzset() as needed. @@ -4919,6 +4920,10 @@ reset_by_modified_env(const char *nam) */ if (ENVMATCH(nam, TZ_ENV)) { ruby_reset_timezone(); + } else if (ENVNMATCH(nam, gc_var_pfx, sizeof(gc_var_pfx) - 1)) { + ENV_LOCK(); + ruby_gc_set_params(); + ENV_UNLOCK(); } } diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 788f2974b5..5fd5924fb3 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -334,6 +334,10 @@ def test_gc_parameter assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_MAX=16000000/, "") assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=2.0/, "") end + + assert_in_out_err(["-w", "-e", <<-'end'], "", [], /RUBY_GC_MALLOC_LIMIT=1024/, "") + ENV['RUBY_GC_MALLOC_LIMIT'] = '1k' + end end def test_profiler_enabled ```