Garbage Collector Tuning in Ruby 1.9

Garbage collector tuning in Ruby 1.9

No.

There is no way to tune the 1.9.0–1.9.2 GC. However, you can compile a custom VM that exposes more or less the same tuning parameters as REE with this patch.

Garbage collector tuning in Ruby 2.0

There's a fair bit of confusion about these GC tuning parameters. REE (which is a fork of Ruby 1.8.7) introduced its own parameters first, and later Ruby (starting in 1.9.2) introduced its own (similar) parameters. Ruby 1.9.3 made them customizable via environment variables, and Ruby 2.1.0 added a lot more.

This blog post goes into great detail about garbage collection in MRI and what all the tuning variables mean.

Here's a complete list of all the tuning variables for each Ruby version:

REE source

  • RUBY_HEAP_MIN_SLOTS
  • RUBY_HEAP_SLOTS_INCREMENT
  • RUBY_HEAP_SLOTS_GROWTH_FACTOR
  • RUBY_GC_MALLOC_LIMIT
  • RUBY_HEAP_FREE_MIN

Ruby 1.9.2 source source

(Hard-coded, but customizable via environment variables with this patch)

  • GC_MALLOC_LIMIT
  • HEAP_MIN_SLOTS
  • FREE_MIN

Ruby 1.9.3 source

  • RUBY_GC_MALLOC_LIMIT
  • RUBY_HEAP_MIN_SLOTS
  • RUBY_FREE_MIN

Ruby 2.0.0 source

Same as Ruby 1.9.3

Ruby 2.1.0 source

  • RUBY_GC_HEAP_INIT_SLOTS (obsoletes RUBY_HEAP_MIN_SLOTS)
  • RUBY_GC_HEAP_FREE_SLOTS (obsoletes RUBY_FREE_MIN)
  • RUBY_GC_HEAP_GROWTH_FACTOR (new)
  • RUBY_GC_HEAP_GROWTH_MAX_SLOTS (new)
  • RUBY_GC_MALLOC_LIMIT
  • RUBY_GC_MALLOC_LIMIT_MAX (new)
  • RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR (new)
  • RUBY_GC_OLDMALLOC_LIMIT (new)
  • RUBY_GC_OLDMALLOC_LIMIT_MAX (new)
  • RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR (new)

Ruby 2.1.1 source

  • RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR (new)

Ruby GC execution exceeding ~250-320ms per request

You're spending so much time in GC because you're running your GC so often. Ruby, by default, sets GC parameters that are appropriate for small scripts, not large apps. Try launching your app with the following environment parameters set:

RUBY_HEAP_MIN_SLOTS=800000
RUBY_FREE_MIN=100000
RUBY_GC_MALLOC_LIMIT=79000000

What this'll do is increase the initial heap allocation size and pad the GC numbers so that it doesn't run quite so often. This may let your app use a bit more RAM, but it should reduce the time spent in GC dramatically. Under the default settings, you're likely running GC multiple times per request; you want to be ideally be running it once every few requests (or even better, between requests with something like Unicorn's OOB::GC).

Those are my GC settings for my app, and you'll want to tweak them up and down as is most appropriate for your app to find the right settings; you're gunning for a middle ground where you aren't running GC so often, and don't have excessive memory usage. This is specific to each app, though, so there's no boilerplate advice I can give on what those exact settings should be. Increasing from the defaults (10k slots, 1.8x growth factor) should have an immediate impact, and you can tweak up and down from there as best fits your current situtation.

There's a full writup of these parameters here and more information here, and while those posts were written for REE 1.8.7, they're applicable to Ruby 1.9.2+ as well.

Those are some rather extreme numbers, so it's possible that you're doing something in your app that is causing you to allocate much more RAM than you should, so I'd encourage you to be suspicious and comb through your app looking for over-eager allocations. The GC environment variables should help triage the situation in any case, though.

Ruby on Rails - Slow loading and spending a massive amount of time in garbage collector

Your rails log shows most of the time (75%) is spent in view code.

Your profile report shows three obvious hotspots: Module#define_method for self time, Module#class_eval for total time, and Set#initialize.

define_method and class_eval indicate there's likely a lot of dynamic code execution which seems excessive to me -- generally you want to generate that code early and reuse it instead of repeatadly re generating it. It almost certainly is part of the problem with your excessive object allocation issues. Producing a graph report instead of a flat report should help you find the parent methods which are falling into these expensive paths and that may give you a pointer to where you could optimize.

Set#initialize may be a real artifact of what your code needs to do, or it might be a sign that there's some significant Set[...] or Set::new set creation calls inline which could be done once and assigned to a constant or instance/class var for reuse.

ruby-prof is ok, but you might want to also try perftools.rb which is easy to hook up to rack rails with rack-perftools_profiler. perftools has some enhanced visualization tools which can make it much easier to understand hot execution paths.

Since you're running REE and extensive object allocation (and hence garbage collection) is an issue, you could try memprof to get some insight into what and where all these allocations are coming from.

If you can't find a path to reducing the amount of objects being allocated, you could ease the GC burden at the expense of larger process memory size by tuning the GC to prealloc a heap large enough to hold a typical request's allocation demands. Unicorn offers a rack module for out of band GC. You might be able to adapt this module's approach to work with thin and move all the GC time to between requests -- you'll still pay the cpu cost, but at least you won't delay your responses for garbage collection.

Performance issues when upgrading from ruby 1.9.3 to 2.2.2

It appears that the cause of the performance drop related to garbage collection. We managed to realise a significant improvement in performance by setting RUBY_GC_MALLOC_LIMIT=90000000

We used the following as a resource
https://meta.discourse.org/t/tuning-ruby-and-rails-for-discourse/4126

Ruby Malloc Limit: How to raise it higher

If you are still looking for this you could try the malloc gem. You can custom set malloc items:

m = Malloc.new(1048576) #Number of bytes to allocate


Related Topics



Leave a reply



Submit