Skip to content

Instantly share code, notes, and snippets.

@monorkin
Last active September 17, 2016 21:23
Show Gist options
  • Save monorkin/b25a7e4c4b2456d4887d75a25226e64a to your computer and use it in GitHub Desktop.
Save monorkin/b25a7e4c4b2456d4887d75a25226e64a to your computer and use it in GitHub Desktop.
# Example 1
module Logger
extend self
attr_accessor :output, :log_actions
def log(&event)
self.log_actions ||= []
self.log_actions << event
end
def play
output = []
log_actions.each { |e| e.call(output) }
puts output.join("\n")
end
end
class Thing
def initialize(id)
Logger.log { |output| output << "created thing #{id}" }
end
end
def do_something
1000.times { |i| Thing.new(i) }
end
do_something
GC.start
Logger.play
Logger.log_actions = nil
GC.start
puts ObjectSpace.each_object(Thing).count # returns 1000
# because each block stores a Thing object in it's closure
# and there are a 1000 blocks in log_actions
# Example 2
module Logger
extend self
attr_accessor :output
def log(&event)
self.output ||= []
event.call(output)
end
def play
puts output.join("\n")
end
end
class Thing
def initialize(id)
Logger.log { |output| output << "created thing #{id}" }
end
end
def do_something
1000.times { |i| Thing.new(i) }
end
do_something
GC.start
Logger.play
puts ObjectSpace.each_object(Thing).count # returns 0
# as expected
# Example 3
module Logger
extend self
attr_accessor :output, :log_actions
def log(&event)
self.log_actions ||= []
self.log_actions << event
end
def play
output = []
log_actions.each { |e| e.call(output) }
puts output.join("\n")
end
end
class Thing
def initialize(id)
Logger.log { |output| output << "created thing #{id}" }
end
end
def do_something
1000.times { |i| Thing.new(i) }
end
do_something
GC.start
Logger.play
Logger.log_actions = nil
GC.start
puts ObjectSpace.each_object(Thing).count # still returns 1000
# Known memory leak - explaned in the first example
# but why are they kept in memory?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment