require 'progressbar' | |
require 'shellwords' | |
require 'json' | |
require 'active_support/core_ext/hash/keys' | |
require 'set' | |
require 'thread' # queue | |
def main | |
objs = load_objs | |
$objs = objs | |
# These object_ids identify ActiveRecord::Relations from the article | |
# table which I'm presuming are the ones that are leaked. I had to find | |
# them in the memprof dump because when I compare | |
# ObjectSpace.each_object(ActiveRecord::Relation) before and after | |
# app.get("/"), the object_ids have a different format than those in the | |
# dump. | |
oids = Set.new ["0x508d418", "0x5413830"] | |
path = search_for(objs, oids) | |
p path | |
end | |
def load_objs | |
filename = "myapp_heap.json" | |
line_count = `wc -l #{filename.shellescape}`.strip.to_i | |
bar = ProgressBar.new "Reading json", line_count | |
objs = {} | |
File.foreach("myapp_heap.json") do |line| | |
obj = JSON.parse(line) | |
obj.symbolize_keys! | |
objs[obj[:_id]] = obj | |
bar.inc | |
end | |
bar.finish | |
objs | |
end | |
def search_for(objs, target_oids) | |
queue = Queue.new | |
$queue = queue | |
seen = Set.new | |
queue.enq ["globals"] # initial | |
until queue.empty? | |
path = queue.deq | |
oid = path.last | |
$stdout.write "#{oid} depth: #{path.length} / queued: #{queue.length} / seen: #{seen.length} \r" | |
next if seen.include? oid | |
seen.add oid | |
if target_oids.include? oid | |
return path | |
end | |
(ch=child_oids(objs[oid])).each do |child| | |
child_path = path.dup | |
child_path.push child | |
queue.enq child_path | |
end | |
end | |
puts | |
end | |
def child_oids(obj) | |
# Perhaps I'm missing some cases here... ? | |
case obj | |
when String | |
if /\A0x[0-9a-f]{1,16}\Z/.match obj | |
[obj] | |
else | |
[] | |
end | |
when Array | |
obj.map {|v| child_oids(v) }.inject([], &:+) | |
when Hash | |
obj.map {|k, v| child_oids(v) }.inject([], &:+) | |
else | |
[] | |
end | |
end | |
if File.identical?(__FILE__, $0) | |
main | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment