设想:
我有一份在生产(heroku)中运行进程(sidekiq)的工作。activerecord-import
该过程使用gem将数据 (CSV) 从 S3 导入数据库模型。这个 gem 有助于批量插入数据。因此,变量在迭代 CSV 行时dbRows
从存储的所有对象中设置了大量内存(一切都很好)。ActiveRecord
一旦数据被导入(在db_model.import dbRows
:)dbRows
被清除(应该是!)并处理下一个对象。
如:(简化脚本以便更好理解)
def import
....
s3_objects.contents.each do |obj|
@cli.get_object({..., key: obj.key}, target: file)
dbRows = []
csv = CSV.new(file, headers: false)
while line = csv.shift
# >> here dbRows grows and grows and never is freed!
dbRows << db_model.new(
field1: field1,
field2: field2,
fieldN: fieldN
)
end
db_model.import dbRows
dbRows = nil # try 1 to freed array
GC.start # try 2 to freed memory
end
....
end
问题:
作业内存在进程运行时增长,但一旦作业完成,内存不会下降。它永远存在!
调试我发现它dbRows
看起来永远不会被垃圾收集,并且我了解了 RETAINED 对象以及内存在 rails 中的工作方式。虽然我还没有找到一种方法来应用它来解决我的问题。
我希望一旦工作完成,在 dbRows 上设置的所有引用都是 GC 并释放工作内存。
任何帮助表示赞赏。
更新:我读过weakref
但我不知道是否有用。有什么见解吗?