Раздувание памяти при создании множества новых объектов

когда я запускаю это, а затем наблюдаю потребление памяти моего процесса ruby в OSX Activity Monitor, память увеличивается примерно на 3 МБ/с.

Если я удалю транзакцию, это примерно вдвое сократит потребление памяти, но все же объем памяти продолжает расти. У меня есть проблема в моем производственном приложении, где Heroku убивает процесс из-за его потребления памяти.

есть ли способ сделать ниже, Таким образом, чтобы не увеличить память? Если я прокомментирую .save line тогда все в порядке, но, конечно, это не решение.

ActiveRecord::Base.transaction do
  10000000.times do |time|
    puts "---- #{time} ----"
    a = Activity.new(:name => "#{time} Activity")
    a.save!(:validate => false)
    a = nil
  end
end

я запускаю это с помощью delayed_job.

2 ответов


на a = nil строка не нужна, и вы можете удалить ее.

вы создаете много объектов каждый раз, когда вы цикл-две строки, два хэша и объект активности, поэтому я не удивлен, что вы испытываете высокое использование памяти, тем более, что вы цикл 10 миллионов раз! Кажется, что нет более эффективного способа записи этого кода в память.

единственный способ уменьшить использование памяти-вручную запускать сборщик мусора каждый раз x число итераций. Скорее всего, GC Ruby недостаточно агрессивен. Однако вы не хотите вызывать его каждую итерацию, так как это радикально замедлит ваш код. Может быть, вы могли бы использовать каждые 100 итераций в качестве отправной точки и идти оттуда. Вам придется составить профиль и проверить, что наиболее эффективно.

документация GC здесь.


Я знаю, что это древняя проблема, но я должен предложить другой радикальный подход:

ActiveRecord::Base.transaction do
  10000000.times do |time|
    puts "---- #{time} ----"
    sql = <<SQL
INSERT INTO activities ("name") VALUES ("#{time}")
SQL
    Activity.connection.execute(sql)
  end
end

дело в том, что если вставка настолько проста, и вы уже пропускаете любую проверку ActiveModel, нет причин создавать экземпляр объекта activerecord в первую очередь. Обычно это не больно, но так как в данном случае это причиняет вам боль, я думаю, вы будете использовать гораздо меньше памяти.