Хорошо, это моя вторая попытка отладки проблем с памятью в моем приложении Sinatra. Я полагаю, что на этот раз я привел его в простой пример кода.
Кажется, когда я фильтрую массив через .map(&:some_method)
, это приводит к тому, что элементы в этом массиве не собирают мусор. Выполнение эквивалента .map{|x| x.some_method}
вполне нормально.
Демонстрация: дан простой пример класса:
class C
def foo
"foo"
end
end
Если я запускаю следующее в IRB, оно обычно собирается:
ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
=> [...]
ruby-1.9.2-p180 :002 > b = a.map{|x| x.foo}
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :004 > a = nil
=> nil
ruby-1.9.2-p180 :005 > b = nil
=> nil
ruby-1.9.2-p180 :006 > GC.start
=> nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
=> 0
Так что никаких ссылок на C больше не существует. Хорошо. Но вместо map{|x| x.foo} with map(&:foo)
(который объявлен как эквивалент), он не собирается:
ruby-1.9.2-p180 :001 > a = 10.times.map{C.new}
=> [...]
ruby-1.9.2-p180 :002 > b = a.map(&:foo)
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"]
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :004 > a = nil
=> nil
ruby-1.9.2-p180 :005 > b = nil
=> nil
ruby-1.9.2-p180 :006 > GC.start
=> nil
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){}
=> 10
ruby-1.9.2-p180 :008 >
Это ошибка в рубине? Я попробую больше версий ruby, чтобы убедиться, но это кажется очевидной проблемой. Кто-нибудь знает, что я делаю не так?
Edit:
Я пробовал это в 1.8.7-p352, и это не имеет проблемы. 1.9.3-preview1 имеет , но проблема остается. Отчет об ошибке в порядке или я что-то не так делаю?
Edit2: форматирование (почему четыре строки перед каждой строкой дают подсветку синтаксиса, а теги <pre>
нет?)