У меня небольшая проблема с утечкой памяти в скрипте Mechanize Ruby.
Я "в то время как цикл" несколько веб-страниц обращаются навсегда, и память увеличивается в каждом цикле. Это создало «не удалось выделить память» через несколько минут и завершил работу скрипта.
На самом деле, кажется, что метод agent.get
создает экземпляр и хранит результат, даже если я присваиваю результат той же "локальной переменной" или даже "глобальной переменной".
Поэтому я попытался присвоить nil
переменной после последнего использования и перед повторным использованием переменной с тем же именем. Но похоже, что предыдущие agent.get
результаты все еще находятся в памяти и действительно не знают, как истощать ОЗУ, чтобы мой сценарий использовал примерно стабильный объем памяти в нерабочее время?
Вот два кода: (оставайтесь на клавише "ввод" и наблюдайте, как увеличивается объем выделенной памяти в Ruby)
#!/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
В других языках на переменную влияют повторно, и выделенная память остается стабильной. почему рубин нет? Как я могу заставить экземпляры мусора?
Редактировать:
Вот еще один пример использования Object, поскольку 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/')