Class: HeapProfiler::Index

Inherits:
Object
  • Object
show all
Defined in:
lib/heap_profiler/index.rb

Constant Summary collapse

BUILTIN_CLASSES =
{
  FILE: "File",
  ICLASS: "ICLASS",
  COMPLEX: "Complex",
  RATIONAL: "Rational",
  BIGNUM: "Bignum",
  FLOAT: "Float",
  ARRAY: "Array",
  STRING: "String",
  HASH: "Hash",
  SYMBOL: "Symbol",
  MODULE: "Module",
  CLASS: "Class",
  REGEXP: "Regexp",
  MATCH: "MatchData",
  ROOT: "<VM Root>",
  SHAPE: "SHAPE",
}.freeze
IMEMO_TYPES =
Hash.new { |h, k| h[k] = "<#{k || 'unknown'}> (IMEMO)" }
DATA_TYPES =
Hash.new { |h, k| h[k] = "<#{k || 'unknown'}> (DATA)" }

Instance Method Summary collapse

Constructor Details

#initialize(heap) ⇒ Index

Returns a new instance of Index.



5
6
7
8
9
10
11
# File 'lib/heap_profiler/index.rb', line 5

def initialize(heap)
  @heap = heap
  @classes = {}
  @strings = {}
  @gems = {}
  build!
end

Instance Method Details

#build!Object



13
14
15
16
# File 'lib/heap_profiler/index.rb', line 13

def build!
  @classes, @strings = Parser.build_index(@heap.path)
  self
end

#guess_class(object) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/heap_profiler/index.rb', line 40

def guess_class(object)
  type = object[:type]
  if (class_name = BUILTIN_CLASSES[type])
    return class_name
  end

  return IMEMO_TYPES[object[:imemo_type]] if type == :IMEMO

  class_name = if (class_address = object[:class])
    @classes.fetch(class_address) do
      return DATA_TYPES[object[:struct]] if type == :DATA

      $stderr.puts("WARNING: Couldn't infer class name of: #{object.inspect}")
      nil
    end
  end

  if type == :DATA && (class_name.nil? || class_name == "Object")
    DATA_TYPES[object[:struct]]
  else
    class_name
  end
end

#guess_gem(object) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/heap_profiler/index.rb', line 73

def guess_gem(object)
  path = object[:file]
  @gems[path] ||=
    if %r{(/gems/.*)*/gems/(?<gemname>[^/]+)} =~ path
      gemname
    elsif %r{/rubygems[\./]}.match?(path)
      "rubygems"
    elsif %r{ruby/2\.[^/]+/(?<stdlib>[^/\.]+)} =~ path
      stdlib
    elsif %r{(?<app>[^/]+/(bin|app|lib))} =~ path
      app
    else
      "other"
    end
end

#string_value(object) ⇒ Object



64
65
66
67
68
69
70
71
# File 'lib/heap_profiler/index.rb', line 64

def string_value(object)
  value = object[:value]
  return value if value

  if object[:shared]
    @strings[Native.parse_address(object[:references].first)]
  end
end