gpt4 book ai didi

ruby-on-rails - 如何追踪 Rails 应用程序中的内存泄漏?

转载 作者:行者123 更新时间:2023-12-04 08:47:13 26 4
gpt4 key购买 nike

我的 Rails 应用程序中有一个类,用于评估应用程序在业务流程中的位置。为此,我有一个 Task 模型的概念,它使用单表继承来提供多态性。 Task 的每个子类都可以通过执行自己的数据库查询来确定它是否完成,通常是通过多态关联在关联模型上进行。
每次运行此评估器时都会消耗更多内存,并且即使在手动调用 GC.start 后也不会释放。 .使用 ObjectSpace.object_counts我制作了一个图表,显示了随 TOTAL 增长的最密切相关的对象类型。数数。 T_IMEMO增长最快,T_STRING排在第二位。
Stats from ObjectSpace.object_counts
内存分析器告诉我大部分内存都分配给了 ActiveRecord。但是在迭代之间,我没有保留新的 ActiveRecord 对象。代码大致如下:

CustomerApplication.all.in_batches(of: 10).each do |batch|
batch.each do |customer_application|
Evaluator.new(customer_application).evaluate!
GC.start
# collect statistics
end
end
据我所知,我没有使用任何可以在迭代之间存储数据的类属性或全局变量。
我还尝试在每次迭代时禁用 ActiveRecord 日志记录并清除 ActiveRecord 缓存。
核心 Evaluator代码如下所示:
class Evaluator
# ...

def stage(name, &block)
stage = Stage.new(@customer_application)
stage.instance_eval(&block) if block_given?
@stages << stage
end

def evaluate!
@stages = []

stage :first_stage do
step :first_step do
task(Task::SpecificTask)
phantom_task(Task::ReportTask, reference: ..., key: 'report_a')
end
end

stage :second_stage do
step :first_step do
task(Task::ReportTask, reference: ..., key: 'report_a')
end

step :second_step do
task(Task::ReportTask, reference: ..., key: 'report_b')
end
end

# A ton more stages/steps/tasks

Task.transaction do
self.tasks.each do |task|
task.enabled = true
task.evaluate_completion!
task.evaluate_optional!

task.save!
end

# Disable all other tasks
end
end
end

class Stage
# ...

private

def step(name, reference: nil, deps: [], &block)
step = Step.new(name, @customer_application, reference, deps)
step.instance_eval(&block) if block_given?
@steps << step
step
end
end

class Step
# ...

private

def task(klass, reference: nil, key: nil)
existing_task = @customer_application.tasks.find_by(type: klass.name, reference: reference, key: key)

task = (existing_task || klass.new(customer_application: @customer_application, reference: reference, key: key))

@tasks << task

task
end

def phantom_task(klass, reference: nil, key: nil)
readonly_klass =
Class.new(klass) do
def self.name
superclass.name
end

def readonly?
true
end

def optional?
true
end

def phantom_task?
true
end
end

task = readonly_klass.new(customer_application: @customer_application, reference: reference, key: key)

@tasks << task

task
end
end

最佳答案

我设法弄明白了。我在每次迭代时实例化运行时类,这些类显然没有被 GC 处理。重构不使用 Class.new解决了这个问题。
所以如果有人在谷歌上搜索这个,Class.new造成内存泄漏。

关于ruby-on-rails - 如何追踪 Rails 应用程序中的内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64251309/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com