ruby-on-rails – rails高内存使用率

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – rails高内存使用率前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我打算使用延迟工作来运行一些后台分析.在我的初始测试中,我看到了大量的内存使用,所以我基本上创建了一个非常简单的任务,每2分钟运行一次,只是为了观察正在使用多少内存.

任务很简单,analytics_eligbile?在给定数据的位置时,方法总是返回false,所以基本上没有调用重击代码.我在开发中的样本数据中有大约200个帖子.发布has_one analytics_facet.

无论此处的内部逻辑/业务如何,此任务唯一要做的就是调用analytics_eligible?方法每2分钟200次.在4小时内,我的物理内存使用量为110MB,虚拟内存为200MB.只是为了做这么简单的事情!我甚至无法想象,如果用真实的生产数据对10,000个帖子进行真正的分析,这会占用多少内存!当然,它可能无法运行2分钟,更像每30分钟,但我认为它不会飞.

这是在Ubuntu 10.x 64位上运行ruby 1.9.7,rails 2.3.5.我的笔记本电脑有4GB内存,双核cpu.

轨道真的很糟糕还是我做错了什么?

Delayed::Worker.logger.info('RAM USAGE Job Start: ' + `pmap #{Process.pid} | tail -1`[10,40].strip)
Post.not_expired.each do |p|
    if p.analytics_eligible?
        #this method is never called
        Post.find_for_analytics_update(p.id).update_analytics
    end
end
Delayed::Worker.logger.info('RAM USAGE Job End: ' + `pmap #{Process.pid} | tail -1`[10,40].strip)

Delayed::Job.enqueue PeriodicAnalyticsJob.new(),2.minutes.from_now

发布模型

def analytics_eligible?
        vf = self.analytics_facet
        if self.total_ratings > 0 && vf.nil?
            return true
        elsif !vf.nil? && vf.last_update_tv > 0
            ratio = self.total_ratings / vf.last_update_tv
            if (ratio - 1) >= Constants::FACET_UPDATE_ELIGIBILITY_DELTA
                return true
            end
        end
        return false
    end

解决方法

ActiveRecord相当需要内存 – 在做选择时要非常小心,并注意Ruby会自动返回块中的最后一个语句作为返回值,这可能意味着你要传回一个记录数组,这些记录会被保存为结果在某处,因此不符合GC的条件.

此外,当您调用“Post.not_expired.each”时,您将所有not_expired帖子加载到RAM中.更好的解决方案是find_in_batches,它一次只能将X记录加载到RAM中.

修复它可能是一件简单的事情:

def do_analytics
  Post.not_expired.find_in_batches(:batch_size => 100) do |batch|
    batch.each do |post|
      if post.analytics_eligible?
        #this method is never called
        Post.find_for_analytics_update(post.id).update_analytics
      end
    end
  end
  GC.start
end

do_analytics

这里发生了一些事情.首先,整个事物的作用域是一个函数,以防止变量冲突保持块迭代器的引用.接下来,find_in_batches一次从数据库中检索batch_size对象,并且只要您不构建对它们的引用,就可以在每次迭代运行后获得垃圾回收的资格,从而减少总内存使用量.最后,我们在方法结束时调用GC.start;这会强制GC开始扫描(你不想在实时应用程序中进行扫描,但由于这是一个后台工作,如果运行需要额外的300毫秒就没关系).如果返回nil,它也有非常明显的好处,这意味着该方法的结果是nil,这意味着我们不会意外地挂起从finder返回的AR实例.

使用这样的东西应该确保你不会得到泄漏的AR对象,并且应该大大提高性能和内存使用.你需要确保你没有在你的应用程序的其他地方泄漏(类变量,全局变量和类引用是最严重的违规者),但我怀疑这将解决你的问题.

所有这一切,在我看来,这是一个cron问题(定期重复工作),而不是DJ问题.您可以使用一次性分析解析器,每隔X分钟使用脚本/运行程序运行您的分析,由cron调用,它可以非常巧妙地清除任何潜在的内存泄漏或每次运行的误操作(因为整个过程在结束时终止)

猜你在找的Ruby相关文章