我已经在我的Rails应用程序中发现了一个操作,每次运行时都会显着增加rails进程使用的内存。每次刷新屏幕时,内存使用量都会以恒定的百分比增加,直到服务器内存不足并且我被迫重启应用程序。
#show
方法执行以下操作:
def show
@report = Report.find(params[:id])
@result = @report.results
@result = @result.paginate(page: params[:page]) if @result
respond_to do |format|
format.html # run.html.erb
format.json { redirect_to "/results/#{@report.id}.json" }
format.csv { redirect_to "/results/#{@report.id}.csv" }
end
end
问题的代码行是@result = @report.results
,它确实:
def results
filename = "public/results/#{self.id}.json"
if File.exists? filename
the_results = File.read(filename)
return JSON.parse(the_results)
end
end
这里,问题是JSON.parse(the_results)
,其中.json文件可能非常大(示例文件为64 Mb)。看来我正在将整个文件加载到内存中以便将其传回控制器,然后控制器进行分页,这不是很好,因为如果我只想在视图中查看30条记录那么我不想加载所有内容。
我有两个问题:
FILE.read
+ JSON.parse
为我的视图加载了所有内容,因此Rails会为此分配大量内存来执行此操作。当我再次这样做时,我希望将相同的内存(Rails进程可以自由使用)用于读取,而不是Rails从操作系统中获取更多内容?FILE.read
+ JSON.parse
,但它会在哪里缓存?控制器?感谢您提供任何帮助,
理查德
答案 0 :(得分:0)
在rails框架中,默认情况下不会缓存读取文件及其内容已解析的部分。
如果可以的话,我建议从数据库表中而不是从文件中读取@report.results
。我假设您没有将结果对象映射到活动记录模型。当你从数据库中获得缓存功能时,可能是一个好主意。
缓存FILE.read + JSON.parse
活动在理论上是可行的,但我认为不切实际。如果自上次读取后文件已更改且文件大小和行数仍然相同,但某些行具有不同的内容,该怎么办?它仍然需要完整读取文件以确认内容没有改变。