From: ara.t.howard@... Date: 2006-08-25T14:33:26+09:00 Subject: Re: Can Anyone Explain This Memory Leak? On Fri, 25 Aug 2006, Zed Shaw wrote: > Hi Folks, > > Sorry to get your attention. :-) > > There's a very strange problem with Mongrel where if Threads are created > because of the Mutex around Rails dispatching, then lots of ram gets > created that never seems to go away. > > I boiled the problem down to this: > > http://pastie.caboo.se/10194 > > It's a graph of the "leak" and the base code that causes it (nothing > Mongrel in it at all). This code kind of simulates how Mongrel is > managing threads and locking Rails. > > What this code does is create threads until there's 1000 in a > ThreadGroup waiting on a Mutex. Inside the guard 30000 integers are put > inside an Array. Don't let this distract you since it can be strings, > or even nothing and you'll see the same thing. It's just to simulate > Rails creating all the stuff it creates, and to demonstrate that while > these objects should go away, they do not. > > Then it waits in 10 second increments for these threads to go away, > calling GC.start each time. > > And what happens is the graph you see (samples of mem usage of the ruby > process 1/second after 3 cycles of create/destroy threads). Rather than > the memory for the threads and the array of integers going away, it > sticks around. It'll dip a little bit, but not much, just tops out > there and doesn't die. Even though all the threads are clearly gone and > none of their contents should be around. > > In contrast, if you remove the Mutex then the ram behaves as you'd > expect, with it going up and then going away. > > I'm hoping people way smarter with Ruby than myself can tell me why this > happens, what is wrong with this code, and how to fix it. > > Thanks. hi zed- i don't think you have a leak. try running under electric fence (ef). when i do i clearly see the memory rise from 1->20% on my desktop, and then decline back down to 1%, over and over with no reported leaks. the cycle matches the logging of the script perfectly. here's the thing though, when i don't run it under electric fence i see the memory climb to about 20% and then stay there forever. but this too does not indicate a leak. it just shows how calling 'free' in a process doesn't really release memory to the os, only to the process itself. the reason you see the memory vary nicely under ef is that it replaces the standard malloc/free with it's own voodoo - details of which i do not understand or care too. the point, however, is that it's 'free' which is doing the 'leaking' - just at the os level, not the process (ruby) level. we have tons of really long running processes that exhibit the exact same behaviour - basically the memory image will climb to maximum and stay there. oddly, however, when you tally them all up the usage exceeds the system capacity plus swap by miles. i think this is just illustraing reason 42 why i prefer Kernel.fork to Thread.new - the only real way to return memory to the os is to exit! ;-) regards. -a -- to foster inner awareness, introspection, and reasoning is more efficient than meditation and prayer. - h.h. the 14th dalai lama