Is there an easy way to run Garbage Collection outside of the request cycle in Passenger?

2.4k Views Asked by At

Unicorn has OobGC rack middleware that can be used to run GC.start after a certain number of requests.

Is there a similar sort of thing in Phusion Passenger?

3

There are 3 best solutions below

4
eric On BEST ANSWER

Hooking into PhusionPassenger::Rack::RequestHandler#process_request() is the only mechanism I have found.

To do this in a similar way to the Unicorn OobGC, you can use the following module:

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"] && ((@@oob_nr -= 1) <= 0)
      @@oob_nr = OOBGC_INTERVAL
      GC.start
    end
  end
end

and invoke it in an initializer with:

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

You have to patch Passenger. Doing a GC.start after each request has been handed off ensures that garbage collection never occurs while holding a client request. This is a one-line change that you might consider if you're trying to reduce your average request time.

In lib/phusion_passenger/abstract_request_handler.rb, patch accept_and_process_next_request and add the GC.start call at the end, with an appropriate interval.

See this commit for an example (thanks, @raphaelcm).

0
Hongli On

Phusion Passenger 4 officially introduces an out of band garbage collection mechanism. It's more flexible than Unicorn's by allowing any arbitrary work, not just garbage collection. http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/