Class: Memory::Sampler

Inherits:
Object
  • Object
show all
Defined in:
lib/memory/sampler.rb

Overview

Sample memory allocations.

~~~ ruby sampler = Sampler.capture do 5.times { “foo” } end ~~~

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&filter) ⇒ Sampler

Returns a new instance of Sampler.



62
63
64
65
66
67
68
# File 'lib/memory/sampler.rb', line 62

def initialize(&filter)
  @filter = filter
  
  @cache = Cache.new
  @wrapper = Wrapper.new(@cache)
  @allocated = Array.new
end

Instance Attribute Details

#allocatedObject (readonly)

Returns the value of attribute allocated.



74
75
76
# File 'lib/memory/sampler.rb', line 74

def allocated
  @allocated
end

#cacheObject (readonly)

Returns the value of attribute cache.



72
73
74
# File 'lib/memory/sampler.rb', line 72

def cache
  @cache
end

#filterObject (readonly)

Returns the value of attribute filter.



70
71
72
# File 'lib/memory/sampler.rb', line 70

def filter
  @filter
end

#wrapperObject (readonly)

Returns the value of attribute wrapper.



73
74
75
# File 'lib/memory/sampler.rb', line 73

def wrapper
  @wrapper
end

Instance Method Details

#dump(io = nil) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/memory/sampler.rb', line 104

def dump(io = nil)
  Console.logger.debug(self, "Dumping allocations: #{@allocated.size}")
  
  if io
    packer = @wrapper.packer(io)
    packer.pack(@allocated)
    packer.flush
  else
    @wrapper.dump(@allocated)
  end
end

#load(data) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/memory/sampler.rb', line 116

def load(data)
  allocations = @wrapper.load(data)
  
  Console.logger.debug(self, "Loading allocations: #{allocations.size}")
  
  @allocated.concat(allocations)
end

#reportObject



124
125
126
127
128
129
130
# File 'lib/memory/sampler.rb', line 124

def report
  report = Report.general
  
  report.concat(@allocated)
  
  return report
end

#run(&block) ⇒ Object

Collects object allocation and memory of ruby code inside of passed block.



133
134
135
136
137
138
139
140
141
142
# File 'lib/memory/sampler.rb', line 133

def run(&block)
  start
  
  begin
    # We do this to avoid retaining the result of the block.
    yield && false
  ensure
    stop
  end
end

#startObject



76
77
78
79
80
81
82
# File 'lib/memory/sampler.rb', line 76

def start
  GC.disable
  GC.start
  
  @generation = GC.count
  ObjectSpace.trace_object_allocations_start
end

#stopObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/memory/sampler.rb', line 84

def stop
  ObjectSpace.trace_object_allocations_stop
  allocated = track_allocations(@generation)
  
  # **WARNING** Do not allocate any new Objects between the call to GC.start and the completion of the retained lookups. It is likely that a new Object would reuse an object_id from a GC'd object.
  
  GC.enable
  3.times{GC.start}
  
  ObjectSpace.each_object do |object|
    next unless ObjectSpace.allocation_generation(object) == @generation
    
    if found = allocated[object.__id__]
      found.retained = true
    end
  end
  
  ObjectSpace.trace_object_allocations_clear
end