reimplemnt oobgc algorithm
This commit is contained in:
parent
3ce6a7be4a
commit
f61920565a
|
@ -5,8 +5,18 @@
|
|||
# hook unicorn
|
||||
module Middleware::UnicornOobgc
|
||||
|
||||
MIN_REQUESTS_PER_OOBGC = 5
|
||||
MAX_DELTAS = 25
|
||||
MIN_REQUESTS_PER_OOBGC = 3
|
||||
|
||||
def verbose(msg=nil)
|
||||
@verbose ||= ENV["OOBGC_VERBOSE"] == "1" ? :true : :false
|
||||
if @verbose == :true
|
||||
if(msg)
|
||||
puts msg
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def self.init
|
||||
# hook up HttpServer intercept
|
||||
|
@ -17,21 +27,22 @@ module Middleware::UnicornOobgc
|
|||
puts "Attempted to patch Unicorn but it is not loaded"
|
||||
end
|
||||
|
||||
# the closer this is to the GC run the more accurate it is
|
||||
def estimate_live_num_at_gc(stat)
|
||||
stat[:heap_live_num] + stat[:heap_free_num]
|
||||
end
|
||||
|
||||
def process_client(client)
|
||||
stat = GC.stat
|
||||
|
||||
@previous_deltas ||= []
|
||||
@num_requests ||= 0
|
||||
@num_requests += 1
|
||||
|
||||
# only track N deltas
|
||||
if @previous_deltas.length > MAX_DELTAS
|
||||
@previous_deltas.delete_at(0)
|
||||
end
|
||||
|
||||
gc_count = stat[:count]
|
||||
live_num = stat[:heap_live_num]
|
||||
|
||||
@expect_gc_at ||= estimate_live_num_at_gc(stat)
|
||||
|
||||
super(client) # Unicorn::HttpServer#process_client
|
||||
|
||||
# at this point client is serviced
|
||||
|
@ -41,25 +52,32 @@ module Middleware::UnicornOobgc
|
|||
|
||||
# no GC happened during the request
|
||||
if new_gc_count == gc_count
|
||||
@previous_deltas << (new_live_num - live_num)
|
||||
delta = new_live_num - live_num
|
||||
|
||||
if @gc_live_num && @num_requests > MIN_REQUESTS_PER_OOBGC
|
||||
largest = @previous_deltas.max
|
||||
if (largest * 3) + new_live_num > @gc_live_num
|
||||
# While tuning consider printing this out, each time this happens you saved
|
||||
# a user from running a GC inline
|
||||
@max_delta ||= delta
|
||||
|
||||
# t = Time.now
|
||||
GC.start
|
||||
# puts "OobGC invoked req count: #{@num_requests} largest delta: #{largest} #{((Time.now - t) * 1000).to_i}ms saved"
|
||||
@num_requests = 0
|
||||
end
|
||||
if delta > @max_delta
|
||||
new_delta = (delta * 1.5).to_i
|
||||
@max_delta = [new_delta, delta].min
|
||||
else
|
||||
new_delta = (delta * 0.99).to_i
|
||||
@max_delta = [new_delta, delta].max
|
||||
end
|
||||
|
||||
if @num_requests > MIN_REQUESTS_PER_OOBGC && @max_delta * 2 + new_live_num > @expect_gc_at
|
||||
t = Time.now
|
||||
GC.start
|
||||
stat = GC.stat
|
||||
@expect_gc_at = estimate_live_num_at_gc(stat)
|
||||
verbose "OobGC hit pid: #{Process.pid} req: #{@num_requests} max delta: #{@max_delta} expect at: #{@expect_gc_at} #{((Time.now - t) * 1000).to_i}ms saved"
|
||||
@num_requests = 0
|
||||
end
|
||||
else
|
||||
puts "OobGC: GC live num adjusted: old live_num #{@gc_live_num} new: #{live_num} - reqs since GC: #{@num_requests} largest delta: #{@previous_deltas.max}"
|
||||
|
||||
verbose "OobGC miss pid: #{Process.pid} reqs: #{@num_requests}"
|
||||
|
||||
@num_requests = 0
|
||||
@gc_live_num = live_num
|
||||
@expect_gc_at = estimate_live_num_at_gc(stat)
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue