Memory SourceMemorySampler

class Sampler

Sample memory allocations.

sampler = Sampler.capture do
	5.times { "foo" }
end

Definitions

def run(&block)

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

Implementation

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

def track_allocations(generation)

Iterates through objects in memory of a given generation. Stores results along with meta data of objects collected.

Implementation

def track_allocations(generation)
	rvalue_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
	
	allocated = Hash.new
	
	ObjectSpace.each_object do |object|
		next unless ObjectSpace.allocation_generation(object) == generation
		
		file = ObjectSpace.allocation_sourcefile(object) || "(no name)"
		
		klass = object.class rescue nil
		
		unless Class === klass
			# attempt to determine the true Class when .class returns something other than a Class
			klass = Kernel.instance_method(:class).bind(object).call
		end
		
		next if @filter && !@filter.call(klass, file)
		
		line = ObjectSpace.allocation_sourceline(object)
		
		# we do memsize first to avoid freezing as a side effect and shifting
		# storage to the new frozen string, this happens on @hash[s] in lookup_string
		memsize = ObjectSpace.memsize_of(object)
		class_name = @cache.lookup_class_name(klass)
		value = (klass == String) ? @cache.lookup_string(object) : nil
		
		# compensate for API bug
		memsize = rvalue_size if memsize > 100_000_000_000
		
		allocation = Allocation.new(@cache, class_name, file, line, memsize, value, false)
		
		@allocated << allocation
		allocated[object.__id__] = allocation
	end
	
	return allocated
end