Fix string memory leaks in Ruby 1.8.6
09.04.09 - 11:07am
UPDATE: This is rails-incompatible... which sucks.
Ruby 1.8.6 leaks memory in some surprising places. Even gsub and split on the String class cause some bad headaches. If you're using Haml and 1.8.6 - you are probably in a bit of trouble.
Read more: http://blog.edhickey.com/2008/12/03/memory-leak-in-ruby-186-string-class/
However, simply overwriting the offending methods fixes this memory leak at least. With a weird caveat that you may not use $ variables (eg $1) in any blocks passed to gsub.
Re-read that last sentence... "boom".gsub(/b(.)/) {|m| $1.upcase} will NO LONGER work. Unfortunately... rails uses that syntax, making this blog post probably moot
RUBY:
class ::String
# This below fixes a bad memory leak in ruby 1.8.6
# http://blog.edhickey.com/2008/12/03/memory-leak-in-ruby-186-string-class/
alias :non_garbage_split :split
alias :non_garbage_gsub :gsub
alias :non_garbage_gsub! :gsub!
def split(char)
holder = char
non_garbage_split(holder)
end
def gsub(*args, &block)
if args.size == 1
non_garbage_gsub(args[0], &block)
else
non_garbage_gsub(args[0], args[1], &block)
end
end
def gsub!(*args, &block)
holder = args[0]
args[0] = holder
non_garbage_gsub!(*args, &block)
end
#end memory leak fixes
end
# This below fixes a bad memory leak in ruby 1.8.6
# http://blog.edhickey.com/2008/12/03/memory-leak-in-ruby-186-string-class/
alias :non_garbage_split :split
alias :non_garbage_gsub :gsub
alias :non_garbage_gsub! :gsub!
def split(char)
holder = char
non_garbage_split(holder)
end
def gsub(*args, &block)
if args.size == 1
non_garbage_gsub(args[0], &block)
else
non_garbage_gsub(args[0], args[1], &block)
end
end
def gsub!(*args, &block)
holder = args[0]
args[0] = holder
non_garbage_gsub!(*args, &block)
end
#end memory leak fixes
end
Try something like:
alias mri_gsub gsub
def gsub(*args,&block)
mri_gsub(*args,&block)
end
It handles $1 et al fine. Also, you should do the same trick with sub, sub!, etc.
– MarkusQ
My bad, I failed to test it thoroughly. It works for special cases, but what is needed is a “works always.”
– Markus
P.S. After looking at the C code (and this time testing before I post) I see that File#gets & $_ have the same problem.