ruby /Mechanize "failed to allocate memory"。删除 'agent.get' 方法的实例化?

标签 ruby mechanize ram

我在 Mechanize Ruby 脚本中遇到了一个关于内存泄漏的小问题。

我“while循环”多个网页永远访问,每次循环内存都会增加很多。这在几分钟后创建了“无法分配内存”并使脚本退出。

事实上,即使我将结果分配给同一个“局部变量”甚至“全局变量”,agent.get 方法也会实例化并保存结果。 因此,我尝试在上次使用后和重用同名变量之前将 nil 分配给该变量。但似乎之前的 agent.get 结果仍然在内存中,并且真的不知道如何耗尽 RAM 以使我的脚本在几小时后使用大致稳定的内存量?

这里有两段代码:(按住“enter”键并看到 Ruby 分配的 RAM 不断增长)

#!/usr/bin/env ruby

require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Windows Mozilla'
GC.enable
#puts GC.malloc_allocations
while gets.chomp!="stop"
    page = agent.get 'http://www.nypost.com/'
    puts "agent.object_id  : "+agent.object_id.to_s
    puts "page.object_id  : "+page.object_id.to_s
    page=nil
    puts "page.object_id  : "+page.object_id.to_s
    page = agent.get 'http://www.nypost.com/'
    puts "page.object_id  : "+page.object_id.to_s
    page=nil
    puts "page.object_id  : "+page.object_id.to_s
    puts local_variables
    GC.start
    puts local_variables
    #puts GC.malloc_allocations
end

并用全局变量代替:

#!/usr/bin/env ruby

require 'mechanize'

agent = Mechanize.new
agent.user_agent_alias = 'Windows Mozilla'
while gets.chomp!="stop"
    $page = agent.get 'http://www.nypost.com/'
    puts "agent.object_id  : "+agent.object_id.to_s
    puts "$page.object_id  : "+$page.object_id.to_s
    $page = agent.get 'http://www.nypost.com/'
    puts "$page.object_id  : "+$page.object_id.to_s
    #puts local_variables
    #puts global_variables
end

在其他语言中,变量会重新受到影响,并且分配的内存保持稳定。为什么 ruby 没有?如何强制实例变成垃圾?

编辑: 这是使用对象的另一个示例,因为 Ruby 是一种面向对象的语言,但结果完全相同:内存一次又一次增长...

#!/usr/bin/env ruby

require 'mechanize'

$agent = Mechanize.new
$agent.user_agent_alias = 'Windows Mozilla'
class GetContent
    def initialize url
        while true
            @page = $agent.get url
            remove_instance_variable(:@page)
        end
    end
end
myPage = GetContent.new('http://www.nypost.com/')

我的答案(没有足够的声誉来正确地做到这一点)

好吧!

看来Mechanize::History.clear极大地解决了内存泄漏的问题。

如果您想测试之前和之后的情况,这是最后修改的 Ruby 代码...

#!/usr/bin/env ruby

require 'mechanize'

$agent = Mechanize.new
$agent.user_agent_alias = 'Windows Mozilla'
class GetContent
    def initialize url
        while true
            @page = $agent.get url
            $agent.history.clear
        end
    end
end
myPage = GetContent.new('http://www.nypost.com/')

最佳答案

我的建议是设置agent.max_history = 0。如链接问题列表中所述。

这将阻止添加历史记录条目,而不是使用#clear。

这是其他答案的修改版本

#!/usr/bin/env ruby

require 'mechanize'

$agent = Mechanize.new
$agent.user_agent_alias = 'Windows Mozilla'
$agent.max_history = 0
class GetContent
    def initialize url
        while true
            @page = $agent.get url
        end
    end
end
myPage = GetContent.new('http://www.nypost.com/')

关于 ruby /Mechanize "failed to allocate memory"。删除 'agent.get' 方法的实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7191752/

相关文章:

ruby-on-rails - rspec 可以输出使测试失败的值吗?

ruby - 在 Ruby 抓取中逃脱 Mechinze 错误

android - 使用自定义适配器会占用更多 RAM?

qt - qml 中 GUI 屏幕转换的工作原理

html - Textarea 不通过表单发送值

ruby - 处理 Rails 3 中的精确单位

ruby-on-rails - Rails 3 路由错误 - "No Route Matches"

php - python 没有正确上传到 php

python - 如何使用 python mechanize 设置 Referer?

gcc - 在运行时确定 ARM Cortex M3 RAM 大小