Memdump
Memdump is a set of (basic) tools to create and manipulate Ruby object dumps.
Since Ruby 2.1, ObjectSpace can be dumped in a JSON file that represents all allocated objects and their relationships. It is a gold mine of information if you want to understand why your application has that many objects and/or a memory leak.
Processing methods are available as a library, or using the memdump
command-line tool. Just run memdump help for a summary of operations.
NOTE running memdump under jruby really reduces processing times... If you're using rbenv, just do
rbenv shell jruby-9.0.5.0
in the shell where you run the memdump commands.
Installation
Add this line to your application's Gemfile:
gem 'memdump'
And then execute:
$ bundle
Or install it yourself as:
$ gem install memdump
Creating a memory dump
Using rbtrace
The memdump command-line tool can connect to a process where
the excellent rbtrace has been required. Just
start your Ruby application with -r rbtrace, e.g.
ruby -rrbtrace -S syskit run
and find out the process PID using e.g. top or ps (in the following, I assume that the PID is 1234)
Memory dumps are then created with
memdump dump 1234 /tmp/mydump
Since dump_all requires very long, the rbtrace client will return before the
end of the dump with *** timed out waiting for eval response. Check your
application's output for a line saying sendto(14): No such file or directory
[detaching]
Additionally, you might want to enable allocation tracing, which adds to the dump the line/file of the point where the object got allocated but is also very costly from a performance point of view, do
memdump enable-allocation-trace 1234
Manually
It is sometimes more beneficial to do the dumps in specific places
in your application, something the rbtrace method does not allow you to do. In
this case, create memory dumps by calling ObjectSpace.dump_all
require 'objspace'
File.open('/path/to/dump/file', 'w') do |io|
ObjectSpace.dump_all(output: io)
end
Allocation tracing is enabled with
require 'objspace'
ObjectSpace.trace_objects_allocation_start
Analyzing the dump
The first thing you will probably want to do is to run the replace-class command on the dump. It replaces the class attribute, which in the original dump is the reference to the class object, by the class name. This makes reading the dump a lot easier.
memdump replace-class /tmp/mydump
The most basic analysis is done by running stats, which outputs the object count by class. For memory leaks, the diff command allows you to output the part of the graph that involves new objects (removing the "old-and-not-referred-to-by-new")
Beyond that, I usually go back and forth between the memory dump and gephi, a graph analysis application. the gml command allows to convert the memory dump into a graph format that gephi can import. From there, use gephi's layouting and filtering algorithms to get an idea of the most likely objects. Then, you can "massage" the dump using the root_of, subgraph_of and remove-node commands to narrow the dump to its most useful parts.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/doudou/memdump.
License
The gem is available as open source under the terms of the MIT License.