加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails-3 – Rails – 循环卷发请求进食记忆

发布时间:2020-12-17 03:23:00 所属栏目:百科 来源:网络整理
导读:我使用gem Curb(也尝试使用httparty)来执行大量的http请求,这很有效.但在我的一个(rake)任务中(我做了20k请求)我有一个内存问题(Rails“吃掉”超过2GB的RAM,直到没有空闲内存为止). 似乎Rails“不等待”响应并继续循环中的另一个线程,问题是以这种方式会创建
我使用gem Curb(也尝试使用httparty)来执行大量的http请求,这很有效.但在我的一个(rake)任务中(我做了20k请求)我有一个内存问题(Rails“吃掉”超过2GB的RAM,直到没有空闲内存为止).

似乎Rails“不等待”响应并继续循环中的另一个线程,问题是以这种方式会创建很多垃圾收集器未收集的对象(我认为)并且是内存泄漏的原因.

有一种方法可以告诉rails等到响应来了吗? (我试着睡觉,但不是一个稳定的解决方案).

我有这样的伪代码:

def the_start
  while start_date <= end_date do                  # ~ 140 loop 
    a_method_that_do_sub_specifics_call
  end
end

def a_method_that_do_sub_specifics_call
    some_data.each do |r|                          # ~ 180 loop
        do_a_call
        #do something with models (update/create entries,...)
    end
end

def do_a_call                                      # called ~ 25k times
    # with the gem Curb version
    req = Curl::Easy.new do |curl| 
       curl.ssl_verify_peer = false
       curl.url = url
       curl.headers['Content-type'] = 'application/json'
    end
    req.perform

    # actual version,with httparty gem
    req = HTTParty.get("#{url}",:headers => {'Content-type' => 'application/json'})
end

似乎Rails不等待req.perform的结果.

编辑:
尝试过只调用一次Curl :: Easy对象,在调用后使用Curl :: Easy.perform()和req.close(应该隐式调用GC),但没有成功使用大量内存. (我认为)可以解决的唯一解决方案是“阻止”轨道,直到响应出现,但如何?

编辑2
在另一个任务中,我只调用a_method_that_do_sub_specifics_call而没有问题.

编辑3
经过一些性能模式(放置find_each(:batch_size => …),GC.start,…)后,任务工作得更好..现在第一个~100循环(do_a_call)工作正常,之后是内存使用率再次从100Mb跳到2Gb.

解决方法

经过几天的调试,阅读了大量的论坛和帖子,我找到了解决方案:
一个适度的类变量字符串,它会一直增长,直到发生内存泄漏.

我在旅行中获得的一些有用的笔记:

遏制与HTTParty
在这两个执行卷曲请求的宝石之间,性能方面最好的是Curb.
http://bibwild.wordpress.com/2012/04/30/ruby-http-performance-shootout-redux/

注意类变量
我的问题是一个继续增长的debug / info变量字符串类,避免使用垃圾收集器永远不会收集的类变量.
在我的具体情况是:

@status = "#{@status} Warning - response is empty for #{description}n"

执行一些手动垃圾收集
在关键点执行一些手动GC.start以确保释放不再需要的内存.请记住,调用GC.start不会对垃圾收集器执行即时调用,它只会建议它.

调用ActiveRecords数组
调用大型ActiveRecords时使用.find_each,例如:

Model.find_each(:batch_size => 50) do |row|

这每次只执行50(或小于默认值)行的查询,比调用1k行的单个查询更好. (我猜默认的batch_size是1000).

有用的链接:

> http://guides.rubyonrails.org/performance_testing.html
> https://cwiki.apache.org/confluence/display/DTACLOUD/Preventing+memory+leaks+in+Ruby

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读