November 19th, 2007
Ruby memory leaks
They aren’t really common, but they do exist. As with any other garbage collected language, you can still be susceptible to memory leaks. In many cases they can also be very insidious. Say that you have a really large Rails application. After some time it grinds to a halt, CPU bound in GC. It may not even be a leak, it could just be something that creates so much garbage that the collector cannot take care of it.
I gotta admit, I’m not sure how to find such a problem. After getting histograms of objects, and trying to profile it, maybe run with ruby-debug, I would be out of options. Maybe some kind of shotgun technique – shutting down parts of the application, trying to pinpoint the location of the problem.
Now, ordinarily, that would have been the end of my search. A failure. Or maybe several weeks of trying to read through the sources.
The alternative? Run the application in JRuby. See if the same memory leak shows up (remember, it might be a bad interaction with MRI’s runtime system that gives you grief. Or maybe even a bug in MRI Garbage Collector). But if it doesn’t go away, you’re in luck. Wait until the CPU starts chugging for real, and then take a heap dump using the jmap Java SDK tool. Once that’s done, you’ll be sitting with a large honking binary file that you can’t do much with. The standard way of reading it is through jhat, but that don’t give much to go on.
But then I found this wonderful tool called SAP Memory Analyzer. Google it and download it. It’s marvelous. Easily the best heap analyzer I’ve run across in a long time. It’s only flaw is that it runs in Eclipse… But well, it can’t be everything, right?
Once you’ve opened up the file in SAP, you can do pretty much everything. It’s quite self explanatory. The way I usually go about things is to use the core option, and then choose “find_leak”. That almost always gives me some good suspects that I can continue investigating. From there on it’s just to drill down and find out exactly what’s going on.
Tell me if you can do that in any way as easy as that with MRI. I would love to know. But right now, JRuby is kicking butt in this regard.
