Skip to content

Commit 4619728

Browse files
committed
unicorn out of band GC
1 parent c9fd14a commit 4619728

3 files changed

Lines changed: 63 additions & 5 deletions

File tree

config/initializers/99-unicorn.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
if (oobgc=ENV['UNICORN_OOBGC_REQS'].to_i) > 0
2-
require 'unicorn/oob_gc'
3-
Rails.configuration.middleware.insert 0, Unicorn::OobGC, oobgc
1+
if ENV['UNICORN_ENABLE_OOBGC']
2+
require 'middleware/unicorn_oobgc'
3+
Middleware::UnicornOobgc.init
44
end

config/unicorn.conf.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# See http://unicorn.bogomips.org/Unicorn/Configurator.html
22

3-
# RUN out of band GC every 2 requests
4-
# ENV['UNICORN_OOBGC_REQS'] = "2" unless ENV['UNICORN_OOBGC_REQS']
3+
# enable out of band gc out of the box, it is low risk and improves perf a lot
4+
ENV['UNICORN_ENABLE_OOBGC'] = "1"
55

66
discourse_path = File.expand_path(File.expand_path(File.dirname(__FILE__)) + "/../")
77

lib/middleware/unicorn_oobgc.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
# Hook into unicorn, unicorn middleware, not rack middleware
3+
#
4+
# Since we need no knowledge about the request we can simply
5+
# hook unicorn
6+
module Middleware::UnicornOobgc
7+
8+
MIN_REQUESTS_PER_OOBGC = 6
9+
MAX_DELTAS = 20
10+
11+
def self.init
12+
# hook up HttpServer intercept
13+
ObjectSpace.each_object(Unicorn::HttpServer) do |s|
14+
s.extend(self)
15+
end
16+
end
17+
18+
def process_client(client)
19+
stat = GC.stat
20+
21+
@previous_deltas ||= []
22+
@num_requests ||= 0
23+
@num_requests += 1
24+
25+
# only track N deltas
26+
if @previous_deltas.length > MAX_DELTAS
27+
@previous_deltas.delete_at(0)
28+
end
29+
30+
gc_count = stat[:count]
31+
live_num = stat[:heap_live_num]
32+
33+
super(client) # Unicorn::HttpServer#process_client
34+
35+
# at this point client is serviced
36+
stat = GC.stat
37+
new_gc_count = stat[:count]
38+
new_live_num = stat[:heap_live_num]
39+
40+
# no GC happened during the request
41+
if new_gc_count == gc_count
42+
@previous_deltas << (new_live_num - live_num)
43+
44+
if @gc_live_num && @num_requests > MIN_REQUESTS_PER_OOBGC
45+
largest = @previous_deltas.max
46+
if largest * (2 + Random.rand(2)) + new_live_num > @gc_live_num
47+
GC.start
48+
@num_requests = 0
49+
end
50+
end
51+
else
52+
puts "OobGC, GC live num adjusted, GC was not avoided: #{live_num}"
53+
@gc_live_num = live_num
54+
end
55+
56+
end
57+
58+
end

0 commit comments

Comments
 (0)