Module: MemDump
- Defined in:
- lib/memdump.rb,
lib/memdump/cli.rb,
lib/memdump/root_of.rb,
lib/memdump/json_dump.rb,
lib/memdump/out_degree.rb,
lib/memdump/memory_dump.rb,
lib/memdump/remove_node.rb,
lib/memdump/subgraph_of.rb,
lib/memdump/convert_to_gml.rb,
lib/memdump/common_ancestor.rb,
lib/memdump/cleanup_references.rb,
lib/memdump/replace_class_address_by_name.rb
Defined Under Namespace
Classes: CLI, JSONDump, MemoryDump
Class Method Summary
collapse
Class Method Details
.cleanup_references(dump) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# File 'lib/memdump/cleanup_references.rb', line 2
def self.cleanup_references(dump)
addresses = Set.new
records = Array.new
dump.each_record do |r|
addr = (r['address'] || r['root'])
addresses << addr
records << r
end
records.each do |r|
if references = r['references']
references.delete_if { |r| !addresses.include?(r) }
end
end
records
end
|
.common_ancestors(dump, class_name, threshold: 0.1) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# File 'lib/memdump/common_ancestor.rb', line 2
def self.common_ancestors(dump, class_name, threshold: 0.1)
selected_records = Hash.new
remaining_records = Array.new
dump.each_record do |r|
if class_name === r['class']
selected_records[r['address']] = r
else
remaining_records << r
end
end
remaining_records = Array.new
selected_records = Hash.new
selected_root = root_address
dump.each_record do |r|
address = (r['address'] || r['root'])
if selected_root == address
selected_records[address] = r
selected_root = nil;
else
remaining_records << r
end
end
count = 0
while count != selected_records.size
count = selected_records.size
remaining_records.delete_if do |r|
references = r['references']
if references && references.any? { |a| selected_records.has_key?(a) }
address = (r['address'] || r['root'])
selected_records[address] = r
end
end
end
selected_records.values.reverse.each do |r|
if refs = r['references']
refs.delete_if { |a| !selected_records.has_key?(a) }
end
end
end
|
.convert_to_gml(dump, io) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
# File 'lib/memdump/convert_to_gml.rb', line 2
def self.convert_to_gml(dump, io)
io.puts "graph"
io.puts "["
edges = []
dump.each_record do |row|
address = row['address']
io.puts " node"
io.puts " ["
io.puts " id #{address}"
row.each do |key, value|
if value.respond_to?(:to_str)
io.puts " #{key} \"#{value}\""
elsif value.kind_of?(Numeric)
io.puts " #{key} #{value}"
end
end
io.puts " ]"
row['references'].each do |ref_address|
edges << address << ref_address
end
end
edges.each_slice(2) do |address, ref_address|
io.puts " edge"
io.puts " ["
io.puts " source #{address}"
io.puts " target #{ref_address}"
io.puts " ]"
end
io.puts "]"
end
|
.out_degree(dump) ⇒ Object
2
3
4
|
# File 'lib/memdump/out_degree.rb', line 2
def self.out_degree(dump)
records = dump.each_record.sort_by { |r| (r['references'] || Array.new).size }
end
|
.pry(dump) ⇒ Object
19
20
21
|
# File 'lib/memdump.rb', line 19
def self.pry(dump)
binding.pry
end
|
.remove_node(dump, removed_node) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/memdump/remove_node.rb', line 2
def self.remove_node(dump, removed_node)
remaining_records = Hash.new
non_roots = Set.new
dump.each_record do |r|
address = (r['address'] || r['root'])
remaining_records[address] = r
if refs = r['references']
refs.each do |ref_address|
non_roots << ref_address
end
end
end
roots = remaining_records.each_key.
find_all { |a| !non_roots.include?(a) }
queue = roots.dup
selected_records = Hash.new
while !queue.empty?
address = queue.shift
next if address == removed_node
if record = remaining_records.delete(address)
selected_records[address] = record
if refs = record['references']
refs.each do |ref_address|
queue << ref_address
end
end
end
end
selected_records.values.reverse.map do |r|
if refs = r['references']
refs.delete_if { |a| !selected_records.has_key?(a) }
end
r
end
end
|
.replace_class_address_by_name(dump, add_reference_to_class: false) ⇒ Object
Replace the address in the ‘class’ attribute by the class name
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/memdump/replace_class_address_by_name.rb', line 3
def self.replace_class_address_by_name(dump, add_reference_to_class: false)
class_names = Hash.new
iclasses = Hash.new
dump.each_record do |row|
if row['type'] == 'CLASS' || row['type'] == 'MODULE'
class_names[row['address']] = row['name']
elsif row['type'] == 'ICLASS' || row['type'] == "IMEMO"
iclasses[row['address']] = row
end
end
iclass_size = 0
while !iclasses.empty? && (iclass_size != iclasses.size)
iclass_size = iclasses.size
iclasses.delete_if do |_, r|
if (klass = r['class']) && (class_name = class_names[klass])
class_names[r['address']] = "I(#{class_name})"
r['class'] = class_name
r['class_address'] = klass
if add_reference_to_class
(r['references'] ||= Set.new) << klass
end
true
end
end
end
dump.map do |r|
if klass = r['class']
r = r.dup
r['class'] = class_names[klass] || klass
r['class_address'] = klass
if add_reference_to_class
(r['references'] ||= Set.new) << klass
end
end
r
end
end
|
.root_of(dump, root_address) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/memdump/root_of.rb', line 2
def self.root_of(dump, root_address)
remaining_records = Array.new
selected_records = Hash.new
selected_root = root_address
dump.each_record do |r|
address = (r['address'] || r['root'])
if selected_root == address
selected_records[address] = r
selected_root = nil;
else
remaining_records << r
end
end
count = 0
while count != selected_records.size
count = selected_records.size
remaining_records.delete_if do |r|
references = r['references']
if references && references.any? { |a| selected_records.has_key?(a) }
address = (r['address'] || r['root'])
selected_records[address] = r
end
end
end
selected_records.values.reverse.each do |r|
if refs = r['references']
refs.delete_if { |a| !selected_records.has_key?(a) }
end
end
end
|
.subgraph_of(dump, root_address, max_depth: Float::INFINITY) ⇒ Object
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# File 'lib/memdump/subgraph_of.rb', line 2
def self.subgraph_of(dump, root_address, max_depth: Float::INFINITY)
remaining_records = Hash.new
dump.each_record do |r|
address = (r['address'] || r['root'])
remaining_records[address] = r
end
selected_records = Hash.new
queue = [[root_address, 0]]
while !queue.empty?
address, depth = queue.shift
if record = remaining_records.delete(address)
selected_records[address] = record
if (depth < max_depth) && (refs = record['references'])
refs.each do |ref_address|
queue << [ref_address, depth + 1]
end
end
end
end
selected_records.values
end
|