Class: HeapScope::Dominators

Inherits:
Object
  • Object
show all
Defined in:
lib/heapscope/dominators.rb

Overview

Approximate dominator-style analysis via bounded retained-size estimates. Explicitly labeled approximate — not a JVM-style precise dominator tree.

Defined Under Namespace

Classes: Candidate

Instance Method Summary collapse

Constructor Details

#initialize(runtime: Runtime.current, config: HeapScope.config) ⇒ Dominators

Returns a new instance of Dominators.



9
10
11
12
13
# File 'lib/heapscope/dominators.rb', line 9

def initialize(runtime: Runtime.current, config: HeapScope.config)
  @runtime = runtime
  @config = config
  @graph = Graph.new(runtime: runtime, config: config)
end

Instance Method Details

#from_thread_locals(limit: 5) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/heapscope/dominators.rb', line 36

def from_thread_locals(limit: 5)
  roots = []
  Thread.list.each do |thread|
    next unless thread.respond_to?(:keys)

    thread.each_key do |key|
      roots << thread[key]
    rescue StandardError
      next
    end
  end
  top_retainers(roots.compact.first(20), limit: limit)
end

#top_retainers(sample_objects, limit: 10) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/heapscope/dominators.rb', line 15

def top_retainers(sample_objects, limit: 10)
  sample_objects.filter_map do |obj|
    next if obj.nil?

    est = @graph.estimate_retained_size(obj, max_objects: 2_000, max_depth: @config.max_graph_depth)
    Candidate.new(
      class_name: begin
        obj.class.name
      rescue StandardError
        "unknown"
      end,
      shallow: est[:shallow],
      approx_retained: est[:retained],
      objects: est[:objects],
      note: "Approximate retained size via bounded traversal — not a precise dominator."
    )
  rescue StandardError
    nil
  end.sort_by { |c| -(c.approx_retained || 0) }.first(limit)
end