Skip to content

Instantly share code, notes, and snippets.

@gamache
Last active December 25, 2015 10:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gamache/6962565 to your computer and use it in GitHub Desktop.
Save gamache/6962565 to your computer and use it in GitHub Desktop.
Code to test relative performace penalty of invalidating the MRI Ruby method cache, versus performing method resolution manually via method_missing. (Edit 1: pinpoint the overhead of Class.new by comparing it to a trivial Object#extend; thanks @joshjordanwhat! Edit 2: added optional warm-up to make JRuby benchmarks make more sense.)
require 'benchmark'
module A; end
class DefinedMethodStyle
def bust_cache_class(*); Class.new; nil end
def bust_cache_extend(*); Object.new.extend(A); nil end
def dont_bust_cache(*); Object.new; nil end
end
class MethodMissingStyle
def _bust_cache_class(*); Class.new; nil end
def _bust_cache_extend(*); Object.new.extend(A); nil end
def _dont_bust_cache(*); Object.new; nil end
def method_missing(method, *args)
case method
when :bust_cache_class then _bust_cache_class(*args)
when :bust_cache_extend then _bust_cache_extend(*args)
when :dont_bust_cache then _dont_bust_cache(*args)
end
end
end
dms = DefinedMethodStyle.new
mms = MethodMissingStyle.new
n = 1_000_000
if ENV['WARM_UP'] # this helps with JRuby benchmarking
puts "Warming up.\n"
for i in 1..n
dms.bust_cache_extend(i); dms.bust_cache_class(i); dms.dont_bust_cache(i)
mms.bust_cache_extend(i); mms.bust_cache_class(i); mms.dont_bust_cache(i)
end
end
Benchmark.bm do |bm|
puts "\n defined methods, not busting cache:"
bm.report { for i in 1..n; dms.dont_bust_cache(i) end }
puts "\n method_missing dispatch, not busting cache:"
bm.report { for i in 1..n; mms.dont_bust_cache(i) end }
puts "\n defined methods, busting cache with trivial Object#extend:"
bm.report { for i in 1..n; dms.bust_cache_extend(i) end }
puts "\n defined methods, busting cache with Class.new:"
bm.report { for i in 1..n; dms.bust_cache_class(i) end }
puts "\n method_missing dispatch, busting cache with trivial Object#extend:"
bm.report { for i in 1..n; mms.bust_cache_extend(i) end }
puts "\n method_missing dispatch, busting cache with Class.new:"
bm.report { for i in 1..n; mms.bust_cache_class(i) end }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment