Рассмотрим этот фрагмент:
l = []
while 1
l << 'a random 369-characterish string'
end
^C
# ran this for maybe 4 seconds, and it had 27 million entries in l. memory
# usage was 1.6 GB.
l = nil
# no change in memory usage
GC.start
# memory usage drops a relatively small amount, from 1.6 GB to 1.39 GB.
Я нажимаю миллионы элементов в/через структуры данных Ruby и имею некоторые серьезные проблемы с памятью. Этот пример демонстрирует, что даже в случае, когда ссылка на объект не существует, Ruby не будет пропускать [большую часть], даже после явного вызова GC.start
.
Объекты, которые я использую в реальной жизни, выталкивают миллионы элементов в хэш в целом, но хеш используется как временная таблица поиска и обнуляется после завершения какого-либо цикла. Однако память из этой таблицы поиска, по-видимому, никогда не выпускается, и это замедляет мое приложение ужасно и непродолжительно, потому что GC имеет миллионы несуществующих объектов для анализа в каждом цикле. Я работаю над обходным решением с драгоценным камнем sparsehash
, но это не похоже на неразрешимую проблему, которая должна затухать в Ruby runtime. Ссылки четко удалены, и объекты должны быть четко собраны и удалены. Может ли кто-нибудь помочь мне понять, почему этого не происходит?
Я попробовал l.delete_if { |x| true}
по предложению пользователя в #ruby на freenode, но это было очень медленно и также никогда не вызывало заметного освобождения памяти.
Использование ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
.
EDIT:
Для сравнения, это пробег в python3
:
l = []
while 1:
l.append('a random 369-characterish string')
^C
# 31,216,082 elements; 246M memory usage.
l = []
# memory usage drops to 8K (0% of system total)
Тест на python2 показывает почти идентичные результаты.
Я не уверен, достаточно ли этого, чтобы рассмотреть этот недостаток реализации в МРТ или если он просто записал различные подходы к GC. В любом случае, похоже, что Python лучше подходит для использования случаев, которые собирают миллионы элементов в целом через структуры данных и периодически обнуляют структуры (как это можно сделать для временной таблицы поиска).
Кажется, что это должно быть просто.:\