1 # -*- encoding: binary -*-
4 # Run GC after every request, after closing the client socket and
5 # before attempting to accept more connections.
7 # This shouldn't hurt overall performance as long as the server cluster
8 # is at <50% CPU capacity, and improves the performance of most memory
9 # intensive requests. This serves to improve _client-visible_
10 # performance (possibly at the cost of overall performance).
12 # We'll call GC after each request is been written out to the socket, so
13 # the client never sees the extra GC hit it.
15 # This middleware is _only_ effective for applications that use a lot
16 # of memory, and will hurt simpler apps/endpoints that can process
17 # multiple requests before incurring GC.
19 # This middleware is only designed to work with Unicorn, as it harms
20 # keepalive performance.
22 # Example (in config.ru):
24 # require 'unicorn/oob_gc'
26 # # GC ever two requests that hit /expensive/foo or /more_expensive/foo
27 # # in your app. By default, this will GC once every 5 requests
28 # # for all endpoints in your app
29 # use Unicorn::OobGC, 2, %r{\A/(?:expensive/foo|more_expensive/foo)}
30 class OobGC < Struct.new(:app, :interval, :path, :nr, :env, :body)
32 def initialize(app, interval = 5, path = %r{\A/})
33 super(app, interval, path, interval)
37 status, headers, self.body = app.call(self.env = env)
38 [ status, headers, self ]
45 # in Unicorn, this is closed _after_ the client socket
47 body.close if body.respond_to?(:close)
49 if path =~ env['PATH_INFO'] && ((self.nr -= 1) <= 0)