2011-08-25 66 views
2

我有一个关于在Mechanize Ruby脚本中泄漏内存的问题。Ruby /机械化“未能分配内存”。擦除'agent.get'方法的实例化?

我“while while循环”多个网页永久访问,每个循环的内存增加很多。在几分钟后创建了“未能分配内存”并使脚本退出。

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

这里有两个代码和平:(停留在 “ENTER” 键,看到了红宝石分配的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是一种面向对象的语言,但结果是完全一样的:内存连连长...

#!/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/') 
+0

你为什么循环和获取页面多次的修改后的版本,到底是什么? –

+0

因为它不是nypost.com,但我得到一个页面的内容,并通过恢复vote_id和启动其他投票PHP空白页做一些选票...所以我得到一些'睡眠xxx'和RAM内存后刷新主页在每个循环中长大,即使'sleep xxx'减少了增长的影响,我的脚本总是以'failed to allocate memory'错误结束,它不应该......我真的不知道如何阻止'agent .get'方法instentiation。 – cz3ch

回答

2

我的建议是设置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/') 
+0

是的这是我做了不久后,但我无法更新我的答案,每次我在红宝石进展......你的权利! – cz3ch

1

好么! (有足够的声望来正确回答我拥有的问题)

看来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/') 
+0

我不能够感谢你。这个提示*显着*减少了我的脚本下载每个连续文件所需的时间,并减少了内存使用量。机械化似乎仍然有漏洞,但并不像以前那么糟糕。 –