Mam aplikację Rails, która przetwarza dużą (miliony) liczbę rekordów w bazie danych mysql. Gdy zacznie działać, jego wykorzystanie pamięci szybko rośnie z prędkością 50 MB na sekundę. Za pomocą takich narzędzi jak oink udało mi się zawęzić główną przyczynę do jednej pętli, która przechodzi przez wszystkie rekordy w dużej tabeli w bazie danych.Wyciek pamięci Ruby on Rails podczas przechodzenia przez dużą liczbę rekordów; find_each nie pomaga
Rozumiem, że jeśli użyję czegoś w rodzaju Person.all.each, wszystkie rekordy zostaną załadowane do pamięci. Jednak jeśli przejdę na find_each, nadal widzę ten sam problem z pamięcią. Aby jeszcze bardziej wyizolować problem, stworzyłem następujący kontroler testowy, który nie robi nic poza zapętlaniem rekordów. Przypuszczam, że find_each zachowuje tylko małą liczbę obiektów w pamięci za każdym razem, ale użycie pamięci rośnie liniowo podczas jej wykonywania.
class TestController < ApplicationController
def memory_test
Person.find_each do |person|
end
end
Podejrzeń, że ma to do czynienia z buforowaniem ActiveRecord wyników zapytania. Ale sprawdziłem ustawienia środowiska i wszystkie opcje związane z buforowaniem są ustawione na false (używam domyślnych ustawień tworzonych przez szyny). Zrobiłem kilka wyszukiwania w Internecie, ale nie mogłem znaleźć rozwiązania.
Używam szyn 3.1.0 RC1 i Ruby 1.9.2
dzięki!
Domyślam się, że w ActiveRecord istnieje funkcja o nazwie 'find_in_batches'. Może to pomoże kontrolować wybuch pamięci. – rubish
Myślałem też, że wygląda to tak, jakby 'find_each' używał' find_in_batches' pod okładką. Może każdy pojedynczy wiersz jest duży i może skorzystać z opcji ': batch_size' (domyślnie do 1000 wierszy). – Brian
Co to jest kod, który faktycznie robi, że musi przechodzić przez każdy rekord? – Maran