Memory leaky ve standardní knihovně Ruby?
Při hledání memory leaku v mém programu jsem narazil na to, že leakuje dost pravděpodobně stadardní knihovna Ruby. Pro detekci objektů, které zůstavají v paměti, jsem použil memory leak detektor dike.
[Update: Leaky způsobovala chyba v diku! Více na mém blogu zde.]
require 'rubygems'
require 'dike'
Dike.logfactory './log/'
class Leak
def http_call
puts 'making http call'
url = URI.parse('http://www.google.com')
Net::HTTP.start(url.host) do |http|
puts http.get('/').code
end
''
end
end
5.times {
leak = Leak.new
leak.http_call
GC.start
Dike.finger
}
V tomto případě leakuje metoda get, zanechává Net::HTTPFound (HTTPResponse) objekty v paměti. Zaměnění get za request_get leak odstraní.
require 'rubygems'
require 'dike'
Dike.logfactory './log/'
class Leak
def http_call
url = URI.parse('http://www.google.com')
puts 'making the call'
Net::HTTP.start(url.host) {|http|
http.request_get('/') do |response|
response.read_body do |segment|
end
end
}
return ''
end
end
5.times {
leak = Leak.new
leak.http_call
GC.start
Dike.finger
}
V tomto příkladě metoda read_body zanechává v paměti ReadAdapter objekty a kvůli nim tam pak zůstanou i další. Tento problém nastává pouze v případě, že se metodě předá blok. Jinak se ReadAdapter objekt nevytváří a žádný memory leak nenastává.
Nevidím na první, druhý, ani třetí pohled v uvedených příkladech nic podezřelého. Ve zdrojácích knihovny mě také do očí nic nepraštilo. Nic zajímavého jsem ani nevygooglil. Někdo je schopen mi tuhle věc objasnit (co, Davide?:). Další zastávkou bude Ruby mailing list.
Btw,
ruby leak.rb && dike log
Pěknější a ještě pěknější syntaxe mapu
Pokud jste stejně jako Dr. Nic a já líní psát, možná oceníte informaci, že
@users.map &:name
dělá totéž, co
@users.map {|user| user.name }
Dr. Nic je nejenom liný, ale ještě k tomu estét, takže mu přišlo i řetězení těchto mapů ošklivé, a tak zabalil hezčí syntaxi
@users.map_by_foo_and_bar
do gemu map_by_method Celá historie zde.