Отслеживание утечек памяти в коде Ruby - PullRequest
2 голосов
/ 21 февраля 2012

Я не эксперт по поиску этих вещей, но следующие вещи кажутся источниками проблемы и просто хотел проверить, прав ли я, и как с этим бороться:

Все сценарии в основномодин большой цикл, каждая итерация выполняет следующие вещи, я думаю, это может быть связано с утечкой:

  1. Механизированный объект используется для извлечения удаленной страницы
  2. Вызывается функция, которая извлекает или инициализируетAR-объект, но это происходит с переменной с тем же именем
  3. Еще два объекта всегда инициализируются, но с тем же именем соответственно

Как я думаю, поскольку назначается вновь созданный объектДля переменной с тем же именем механизм сборки мусора должен позаботиться об этом ...

Обновлено: упрощенная версия моего кода

runner.rb запускается каждый день cronjob, и это в основном порождает список других скриптов - пауков:

['spider1_path', 'spider2_path', .. ].each do |spider_path|
  Process.detach( fork { exec "ruby #{spider_path}" } )
end

spider.rb

# This is the main bit
#
agent = Mechanize.new { |agent|
  agent.user_agent_alias = 'Mac Safari'
}

categories_urls = get_list_of_categories_links_for_website('a')
categories_urls.each do |category_url|
  next_page = category_url
  while next_page
    doc = fetch_page( next_page, agent )
    cat_page = CategoryPage.new( doc )
    urls_of_sub_pages = cat_page.get_urls_of_sub_pages

    urls_of_sub_pages.each do |url|
      page_doc = fetch_page( url, agent )
      sub_page = SubPage.new( page_doc )
      sub_page.parse!
      sub_page.insert
    end
    next_page = cat_page.get_next_page
    # this bit bellow didn't help
    GC.start
  end
end

...

def fetch_page( a, url )
  a.get url
end

...

class SubPage
  ...
  def parse!
    # @doc - result of `fetch_page`
    @parser = @doc.parser
    # do some scraping using @parser
    # accumulate @attrs hash with necessary information
  end
  ...

  def insert
    ad = Ad.where('advert_id = ?', @attrs['advert_id']).first
    if ad
      ad.update_attributes( @attrs )
    else
      ad = Ad.create(@attrs)
    end
  end
end

Ответы [ 2 ]

1 голос
/ 21 февраля 2012

Вы пытались зазвонить на GC.start, чтобы периодически запускать сборку мусора? Я обнаружил, что при некоторых обстоятельствах Руби может очень лень выносить мусор.

Ruby обычно не "протекает" из памяти, но может накапливать много выделенных объектов, если вы случайно их где-то храните в кэше.

0 голосов
/ 21 февраля 2012

Вы можете попробовать использовать mem-prof или ruby-prof, чтобы профилировать использование памяти и выяснить, где она используется.Но я бы не стал беспокоиться, пока вы на самом деле не заметите проблему утечки памяти.

...