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



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/memory/sampler.rb', line 110

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



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

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

#reportObject



130
131
132
133
134
135
136
# File 'lib/memory/sampler.rb', line 130

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.



139
140
141
142
143
144
145
146
147
148
# File 'lib/memory/sampler.rb', line 139

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
83
84
85
# File 'lib/memory/sampler.rb', line 76

def start
	GC.disable
	3.times{GC.start}
	
	# Ensure any allocations related to the block are freed:
	GC.start
	
	@generation = GC.count
	ObjectSpace.trace_object_allocations_start
end

#stopObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/memory/sampler.rb', line 87

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}
	
	# See above.
	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