This post originated from an RSS feed registered with Ruby Buzz
by Red Handed.
Original Post: I Thought Process::detach Was My Friend
Feed Title: RedHanded
Feed URL: http://redhanded.hobix.com/index.xml
Feed Description: sneaking Ruby through the system
So, Try Ruby has been riddled with problems. At about 9 AM EST yesterday the whole thing was swapping pretty heavily. This was right in the epicenter of the Digg stampede. I mean imagine trying to manage all these hundreds of Ruby processes opening up. CPU is fine, but a single Ruby process will gobble up a good share of memory lickety split.
Try Ruby itself is pretty small, about 350 lines of Ruby code. But yesterday it was consuming 32M of memory per process. The dispatcher would start at 8M, but as it grew, forked children would swell as well.
The problem was Process::detach, which was used to ensure zombie kids get killed. More here. The method moves the $SAFE up and starts a thread which calls waitpid every second. I’m not sure what’s so expense. I think constant switching of $SAFE will do it.
Anyway, the code switched from something like this:
FCGI.each_request do |req|
if req.new_session?
pid = fork { ... }
Process.detach pid
end
end
To a tip from Nobu on ruby-talk:
trap("CHLD") {Process.wait(-1, Process::WNOHANG)}
FCGI.each_request do |req|
if req.new_session?
fork { ... }
end
end
And memory consumption was sliced back down to 8M, the bare allocation. Blink. Blink. I guess I should probably add a waitall at the end of the script, too. Had this not worked, I was gonna do a telethon for another stick of memory. (Anyway, you can read the joyous parade of the diggers enjoyably trampling me until all was well an hour and a half later.)