add Unicorn::OobGC middleware
[unicorn.git] / lib / unicorn / oob_gc.rb
blob8dc4dcfbc168727589c518bc29ff2096b185925d
1 # -*- encoding: binary -*-
2 module Unicorn
4   # Run GC after every request, after closing the client socket and
5   # before attempting to accept more connections.
6   #
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).
11   #
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.
14   #
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.
18   #
19   # This middleware is only designed to work with Unicorn, as it harms
20   # keepalive performance.
21   #
22   # Example (in config.ru):
23   #
24   #     require 'unicorn/oob_gc'
25   #
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)
34     end
36     def call(env)
37       status, headers, self.body = app.call(self.env = env)
38       [ status, headers, self ]
39     end
41     def each(&block)
42       body.each(&block)
43     end
45     # in Unicorn, this is closed _after_ the client socket
46     def close
47       body.close if body.respond_to?(:close)
49       if path =~ env['PATH_INFO'] && ((self.nr -= 1) <= 0)
50         self.nr = interval
51         self.body = nil
52         env.clear
53         GC.start
54       end
55     end
57   end
58 end