Be careful when...

  • using .to_sym, .intern or :"#{string}". Symbols are frozen strings and they are not consumed by Ruby garbage collector.
  • using the @@variable variables, as before, they are not consumed by GC and they stay in memory forever
  • using $variable variables, same as above.
  • YAML.load(File.read('file')) seems to cause memory leaking under 1.9.3p194
  • Fiber seems to also cause different kinds of memory leaking
  • using double quotes, use '' (single quotes) for strings that do not change like: s='PENDING' instead of s="PENDING"

Other hints

  • 'thin' web server is actually a big memory consumer (it is not 'thin' anymore (wink). Comparing to webrick, it eats 100% more resources.

How to debug/profile Ruby

There are few tools available, however none of them works with native MRI Ruby (1.9.3p194).
To simply print the current ruby script memory usage in the system, you can use this function:

def get_current_memory_usage
  `ps -o rss= -p #{Process.pid}`.to_i
end

Also this method will enhance the method above and allow you to print memory footprint
for the block:

def profile_memory(&block)
  before = get_current_memory_usage
  file, line, _ = caller[0].split(':')
  if block_given?
    instance_eval(&block)
    puts "[#{file}:#{line}: #{(get_current_memory_usage - before) / 1024} MB (consumed)]"
  elsehttps://gist.github.com/3912688
    before = 0
    puts "[#{file}:#{line}: #{(get_current_memory_usage - before) / 1024} MB (all)]"
  end
end

I also created a Rack middleware that tracks memory usage for every line of code executed. However this middleware
requires to have patched Ruby 1.9.3 (gcdata.patch) to work. (https://gist.github.com/3912688)

Future reading:

  • No labels