Feature #12967


Add a default for RUBY_GC_HEAP_GROWTH_MAX_SLOTS out-of-the-box

Added by sam.saffron (Sam Saffron) about 7 years ago. Updated almost 6 years ago.

Target version:


As it stands Ruby heaps grow at a rate that is too fast for the vast majority of applications that use Ruby.

def rss
  _,rss = `ps ax -o pid,rss | grep '#{} '`.split(/\s+/)

def heap_length

@array = []
@heap_length = heap_length

while true
  @array << ""
  if @heap_length < heap_length
    @heap_length = heap_length
    puts "RSS #{rss}, Heap length: #{@heap_length}"
RSS 14364, Heap length: 133
RSS 33828, Heap length: 237
RSS 39652, Heap length: 424
RSS 59476, Heap length: 759
RSS 112192, Heap length: 1342
RSS 126452, Heap length: 2257
RSS 142020, Heap length: 3295
RSS 184056, Heap length: 5058
RSS 266648, Heap length: 7810
RSS 339224, Heap length: 11113

compare that to a sane default of say


RUBY_GC_HEAP_GROWTH_MAX_SLOTS=100000 ruby test_mem.rb
RSS 15580, Heap length: 133
RSS 30452, Heap length: 237
RSS 37212, Heap length: 424
RSS 55116, Heap length: 667
RSS 107716, Heap length: 911
RSS 114388, Heap length: 1095
RSS 117492, Heap length: 1233
RSS 119196, Heap length: 1309
RSS 122872, Heap length: 1474
RSS 123588, Heap length: 1509
RSS 125396, Heap length: 1589
RSS 129648, Heap length: 1756
RSS 131096, Heap length: 1781
RSS 132812, Heap length: 1863
RSS 136420, Heap length: 2031
RSS 137960, Heap length: 2052
RSS 139832, Heap length: 2135
RSS 143568, Heap length: 2304
RSS 145112, Heap length: 2322
RSS 146936, Heap length: 2406
RSS 150404, Heap length: 2573
RSS 173660, Heap length: 2781
RSS 175984, Heap length: 2866
RSS 179664, Heap length: 3034
RSS 192980, Heap length: 3242
RSS 193784, Heap length: 3325
RSS 197304, Heap length: 3493

Note, this test deals with the absolute minimal amount of RSS, cause all data is stored in RVALUES, with strings like typical apps RSS can grow in much bigger increments.

RSS will jump from 266MB to 339MB, out of the box, this is a massive amount of growth just for Ruby heaps.

The trouble with this huge amount of heap growth is that it amplifies issues around heap fragmentation, in web apps once heap grows it is very unlikely it will shrink again cause there are just enough long living objects that a full slot never frees up properly.

My suggestion is to ship with a far safer default of: RUBY_GC_HEAP_GROWTH_MAX_SLOTS=100000

This has zero impact on "small scripts" < 50M rss, and major advantages for larger apps.


Honestly I see zero downsides to capping it so Ruby heaps only grow in 5mb increments. It eliminates lots of current bloat and allows the GC to operate more efficiently.


Also available in: Atom PDF