Today I was working on some revisions to Twitter’s Protected User stack { or Project: PrivateParts as I like to refer to it in my head }, when I had to make some string changes to emails being sent to users. Offhandedly, I ran across this bug report on RubyForge.

HOLY HELL IN A HANDBASKET!

The Ruby GetText 1.90.0 gem uses an instance of a Class Object as a key to a hash! Steven Rusitschka noticed this and noted that “the memory Mongrel used increased by 1 MB with each request it served …”

To avoid any possibility of a reader absentmindedly skipping over that last quote from Steven, I present it for you again in vibrant color and with extra bold.

“the memory Mongrel used increased by 1 MB with each request it served …”

Okay. Deep breaths. Before everyone goes around MonkeyPatching GetText, there’s a new release out, 1.91.0. Let’s look and see if a fix has been put into place.

Old: 1.90.0


def bound_target(klass = self) # :nodoc:
  if cached?
    if @@__cache_bound_target[klass] # <---- Yowza!
      return @@__cache_bound_target[klass]
    end
  end

  ret = nil
  if klass.kind_of? Class or klass.kind_of? Module
    ret = klass
  else
    ret = klass.class
  end
  ret = GetText if ret.name =~ /^\#<|^$/
  @@__cache_bound_target[klass] = ret
  ret
end

New: 1.91.0


def bound_target(klass = self) # :nodoc:
  id = klass.object_id
  if cached?
   tgt = @@__cache_bound_target[id] # <---- Ahhh, much better.
   return tgt if tgt
  end

  ret = (klass.kind_of? Module) ? klass : klass.class
  if ret.name =~ /^\#<|^$/ or ret == GetText
     #GC for dead object_ids.
     ret = Object
     if @@__cache_bound_target.size > CACHE_BOUND_TARGET_MAX_SIZE
        @@__cache_bound_target.clear
     end
  end
  @@__cache_bound_target[id] = ret
  ret
end

The GetText gem is now using the object_id as the cache key. To say the least, this has made a huge difference in the memory profile of Twitter’s Mongrels. Not much more to say here. If you’re running GetText with Rails and are find yourself a bit leaky, check your gem version. You may be due for an upgrade!

4 Responses to “Ruby GetText Memory Leaks”

  1. Ian McKellar Says:

    Oh my. Are there any <i>good</i> standard ruby libraries?

  2. Britt Says:

    To be fair, this isn’t a standard library.

  3. Dan Says:

    Ian (and I say this as someone who loves the Ruby language and uses it almost primarily) the vast majority of Ruby’s core and stdlib libraries are really poorly designed and not worthy to be included with the language. The core and stlib are pretty bloated, and at least 80% of the libraries in those packages are rarely used by Ruby programmers. Most of the good stuff is available in external libraries available on github and rubyforge.

    IMHO Ruby needs to remove almost all of its core libraries (aside from the very basic primitives) and decentralize the development process a bit. For example we’d have alot higher quality Net (protocol) and Date (date/time) libraries if we did this.

  4. pragmatig Says:

    yyou might want to check out fast gettext gem, which does not do so much meta-magic and is simple/8xfaster/threadsave http://github.com/grosser/fast_gettext/tree/master


Leave a Reply