2011-08-25 3 views
2

기계화 루비 (Mechanize Ruby) 스크립트에서 메모리 누출에 대해 약간의 문제가 있습니다.Ruby/Mechanize "메모리를 할당하지 못했습니다". 'agent.get'메소드의 인스턴스 지우기?

"while 루프"여러 웹 페이지가 영원히 액세스하고 각 루프에서 메모리가 많이 증가합니다. 그로 인해 "분당 메모리 할당 실패"가 발생하고 스크립트가 종료되었습니다.

사실, agent.get 메서드는 결과를 동일한 "로컬 변수"또는 "전역 변수"에 할당하더라도 결과를 인스턴스화하고 유지하는 것으로 보입니다. 그래서 마지막으로 사용한 후 동일한 이름 변수를 다시 사용하기 전에 nil을 변수에 할당하려고했습니다. 그러나 이전의 agent.get 결과가 여전히 메모리에 남아 있고 시간이 지나면 대략적으로 안정된 양의 메모리를 사용하여 스크립트를 만드는 데 RAM을 어떻게 소모하는지 모릅니다. 여기

코드의 두 평화 있습니다 은 ("입력"키에 머물면서 루비가 할당 된 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 

기타에서 언어는 변수가 다시 영향을 받고 할당 된 메모리가 안정적으로 유지됩니다. 루비가 왜 안되니? 인스턴스를 쓰레기통에 강제로 넣을 수 있습니까?

편집 : 루비는 객체 지향 언어지만 결과는 정확히 동일로 여기 이 객체를 사용하여 다른 예입니다 메모리 또 다시 성장 ...

#!/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이 메모리 누수 문제를 크게 해결 한 것 같습니다. 여기

는 ... 너무 좋아

#!/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이 아니기 때문에 투표 내용을 복구하고 다른 투표 PHP 빈 페이지를 시작하여 일부 투표를합니다 ... 그래서 저는 '잠 xxx'및 RAM 메모리를 사용하여 메인 페이지를 새로 고칩니다 'sleep xxx'가 커지는 효과를 줄이더라도 각 루프에서 자라납니다. 스크립트는 항상'메모리를 할당하지 못했습니다 .' 오류로 끝날 것이고, 그렇게해서는 안됩니다 ... 나는'에이전트를 막는 방법을 이해하지 못합니다. .get' 메소드 instentiation. – cz3ch

답변

2

나의 제안은 0 = agent.max_history 설정입니다 ... 당신이 이전과 이후 테스트하려는 경우 마지막으로 수정 한 루비 코드입니다.

이렇게하면 #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

당신이 이전과 이후 테스트하려는 경우 마지막으로 수정 한 루비 코드입니다! (제 질문에 대한 답변에 충분한 평판을 얻었습니다.)

이 메모리 누수 문제는 크게 해결되었습니다. 여기

링크 된 문제 목록에서 언급 한 바와 같이

#!/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

감사합니다. 이 팁은 스크립트가 각 연속 파일을 다운로드하고 메모리 사용량을 줄이는데 걸리는 시간을 상당히 단축했습니다. Mechanize는 여전히 누출되지만 이전처럼 나쁘지는 않습니다. –

관련 문제