Skip to content

Instantly share code, notes, and snippets.

@serradura
Last active May 25, 2018 07:36
Show Gist options
  • Save serradura/5b72c80eb9c4b11d61bd92926896bff0 to your computer and use it in GitHub Desktop.
Save serradura/5b72c80eb9c4b11d61bd92926896bff0 to your computer and use it in GitHub Desktop.
Ruby closure memory leak labs (Based on https://practicingruby.com/articles/closures-are-complicated)
module LazyLogger
extend self
attr_accessor :output
def log(&callback)
@log_actions ||= []
@log_actions << callback
end
def flush
@log_actions.each { |e| e.call(output) }
end
end
class User
def initialize(id)
@id = id
LazyLogger.log { |out| out << "Created User with ID #{id}" }
end
end
LazyLogger.output = ""
1000.times { |i| User.new(i) }
GC.start
p ObjectSpace.each_object(User).count # => 1000
class User
Log = -> id do
-> out { out << "Created User with ID #{id}" }
end
def initialize(id)
@id = id
LazyLogger.log &Log.curry[id]
end
end
LazyLogger.output = ""
1000.times { |i| User.new(i) }
GC.start
p ObjectSpace.each_object(User).count # => 0
class Module
def private_const(name, value)
const_set(name, value)
private_constant(name)
end
end
class User
private_const :Log, -> (id, out) do
out << "Created User with ID #{id}"
end
def initialize(id)
@id = id
LazyLogger.log &Log.curry[id]
end
end
LazyLogger.output = ""
1000.times { |i| User.new(i) }
GC.start
p ObjectSpace.each_object(User).count # => 0
module Logger
extend self
attr_accessor :output
def log(msg)
output << "#{msg}\n"
end
end
class User
def initialize(id)
@id = id
Logger.log("Created User with ID #{id}")
end
end
Logger.output = ""
1000.times { |i| User.new(i) }
GC.start
p ObjectSpace.each_object(User).count #=> 0
@serradura
Copy link
Author

serradura commented May 25, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment