Есть ли простой способ запустить сборку мусора вне цикла запроса в Passenger?

#ruby-on-rails #ruby #passenger #mod-rails

#ruby-on-rails #ruby #пассажир #mod-rails

Вопрос:

У Unicorn есть промежуточное программное обеспечение для стойки OobGC, которое можно использовать для запуска GC.start после определенного количества запросов.

Есть ли что-то подобное в Phusion Passenger?

Комментарии:

1. Если у вас утечка памяти, почему бы не разобраться с этим напрямую?

2. На самом деле это не утечка памяти, просто иногда мне приходится использовать много памяти. Я бы предпочел использовать GC вне цикла запроса / ответа.

Ответ №1:

Phusion Passenger 4 официально представляет механизм внеполосной сборки мусора. Он более гибкий, чем Unicorn, позволяя выполнять любую произвольную работу, а не только сборку мусора. http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work /

Ответ №2:

Подключение к PhusionPassenger::Rack::RequestHandler#process_request() — единственный механизм, который я нашел.

Чтобы сделать это аналогично Unicorn OobGC, вы можете использовать следующий модуль:

 module PassengerOobGC
  def self.install!(path, interval = 5)
    self.const_set :OOBGC_PATH,     path
    self.const_set :OOBGC_INTERVAL, interval
    @@oob_nr = interval
    PhusionPassenger::Rack::RequestHandler.send :include, self
  end

  def self.included(base)
    base.send :alias_method_chain, :process_request, :gc
  end

  def process_request_with_gc(env, *args)
    process_request_without_gc(env, *args)

    if OOBGC_PATH =~ env["PATH_INFO"] amp;amp; ((@@oob_nr -= 1) <= 0)
      @@oob_nr = OOBGC_INTERVAL
      GC.start
    end
  end
end
  

и вызвать его в инициализаторе с:

 if defined?(PhusionPassenger::Rack::RequestHandler)
  require 'passenger_oob_gc'
  PassengerOobGC.install!(%r{^/admin/}, 3)
end
  

Комментарии:

1. После настройки переменных среды GC (мы используем REE 1.8.7) все идет своим чередом, но когда я добавил этот код для выполнения GC вне цикла req / resp, все замедлилось (значительно; на 50% медленнее). Как приведенный выше код повлиял на производительность для вас?

2. Хм, похоже, это также приводит к поломке агента New Relic. Вы это вообще пересматривали?

3. Итак, этот код просто уничтожает экземпляр моего приложения после завершения запроса, а затем passenger создает новое приложение. Не очень производительный. Просматривали ли вы PID экземпляров вашего приложения при выполнении этого?

4. Я только что протестировал это, заменив GC.start на sleep 10 , и, похоже, это решение неверно (больше), поскольку переход в спящий режим задерживает запрос. Приведенный ниже ответ Мэтью, похоже, работает с другой стороны.

Ответ №3:

Вам нужно исправить Passenger. Выполнение GC.start после отправки каждого запроса гарантирует, что сбор мусора никогда не произойдет при удержании запроса клиента. Это однострочное изменение, которое вы могли бы рассмотреть, если пытаетесь сократить среднее время запроса.

В lib/phusion_passenger/abstract_request_handler.rb исправьте accept_and_process_next_request и добавьте GC.start вызов в конце с соответствующим интервалом.

Смотрите Этот коммит для примера (спасибо, @raphaelcm).

Комментарии:

1. У вас есть ссылка на изменение, на которое вы ссылаетесь?

2. согласно этому сообщению: williambharding.com/blog/uncategorized / … вы можете запускать rails GC между запросами, добавив эту строку кода в Passenger: github.com/wbharding/passenger/commit /…

3. Ах, извините. Я никогда не следил за этим сообщением и только что увидел это обновление. Опубликованный @raphaelcm патч на самом деле является тем, на что я ссылался.