Skip to content

Instantly share code, notes, and snippets.

@olegkovalenko
Forked from arp/allocation_map.rb
Created May 31, 2013 19:09

Revisions

  1. @arp arp created this gist May 31, 2013.
    47 changes: 47 additions & 0 deletions allocation_map.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    # Ruby has #source_location method that returns code location where a method was declared.
    # What Ruby lacks is alike functionality that could show where an object was created.
    # Below is a very rough solution that may help with tracing object allocations
    # by storing the first entry in the caller list during object initialization phase.
    # It doesn't work for built-in classes like Fixnum and for classes that don't invoke #initialize()
    # like the ones derived from ActiveRecord::Base, but can be potentially tailored to address
    # at least the latter case by overriding ActiveRecord::Base.new in addition to overriding #initialize()

    class BasicObject
    attr_reader :allocated_at

    def initialize_with_allocated_at(*options)
    unless @allocated_at
    @allocated_at = caller.first
    return initialize_without_allocated_at(*options)
    end
    end

    def self.enable_allocated_at
    self.send :alias_method, :initialize_without_allocated_at, :initialize
    self.send :alias_method, :initialize, :initialize_with_allocated_at
    end
    end

    ObjectSpace.each_object(Class) do |klass|
    klass.enable_allocated_at
    end

    class Object

    # Call this method to get a hash where
    # keys are strings representing locations in the source code
    # and values are objects allocated at these locations
    #
    # Example:
    # allocation_map(Person) # only show places where Person.new was called
    # or
    # allocation_map() # beware, this may return A LOT of objects
    #
    def allocation_map(*each_object_options)
    ObjectSpace.each_object(*each_object_options).reduce({}) { |hash, object|
    hash[object.allocated_at] ||= []
    hash[object.allocated_at] << object if object.respond_to?(:allocated_at)
    hash
    }
    end
    end