Last active
December 11, 2015 02:08
-
-
Save ridiculous/be52492aea3c17352241 to your computer and use it in GitHub Desktop.
Looks for a correlation between method call time and # classes in the object space
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark' | |
class ScratchNGo | |
#= Class Description | |
# Looks for a correlation between method call time and # classes in the object space. We do this by creating an initial | |
# sample size of new classes, each defined with the same number of methods. We then benchmark the call time for all methods of the | |
# original sample size of classes. We then create additional sets of class samples, measuring the call time of the original | |
# set each time. | |
def initialize(args) | |
@class_size = (args.pop || 5_000).to_i | |
@method_size = 20 | |
end | |
def run | |
puts "Running benchmarks for #{@class_size} classes each with #{@method_size} methods" | |
Benchmark.benchmark do |metrics| | |
metrics.report("+ #{@class_size} classes") { create_classes 'call' } | |
metrics.report("Calling methods ...") { call_methods } | |
metrics.report("+ #{@class_size} classes") { create_classes 'true' } | |
metrics.report("Calling methods ...") { call_methods } | |
metrics.report("+ #{@class_size} classes") { create_classes 'false' } | |
metrics.report("Calling methods ...") { call_methods } | |
metrics.report("+ #{@class_size} classes") { create_classes 'nil' } | |
metrics.report("Calling methods ...") { call_methods } | |
metrics.report("+ #{@class_size} classes") { create_classes 'class' } | |
metrics.report("Calling methods ...") { call_methods } | |
metrics.report("+ #{@class_size} classes") { create_classes 'module' } | |
metrics.report("Calling methods ...") { call_methods } | |
end | |
end | |
def call_methods(name_prefix = 'call') | |
@classes ||= classes.select { |klass| klass.respond_to?("#{name_prefix}_0") } | |
@classes.each do |klass| | |
methods = klass.public_methods - Object.methods | |
methods.each do |method_name| | |
klass.allocate.send(method_name) | |
end | |
end | |
end | |
def create_classes(name_prefix) | |
@class_size.times do | |
klass_name = generate_class_name | |
klass = Class.new(Object) | |
@method_size.times do |i| | |
klass.send :define_method, "#{name_prefix}_#{i}", ->() {} | |
klass.define_singleton_method "#{name_prefix}_#{i}", ->() {} | |
end | |
Object.const_set klass_name, klass | |
end | |
end | |
def generate_class_name | |
words.sample(2).map(&:capitalize).join.gsub /\W/, '' | |
end | |
def classes | |
ObjectSpace.each_object(Class).lazy | |
end | |
def words | |
@words ||= File.readlines('/usr/share/dict/words').map(&:chomp) | |
end | |
end | |
ScratchNGo.new(ARGV).run | |
# $ ruby scratch_n_go.rb | |
# Running benchmarks for 5000 classes each with 20 methods | |
# + 5000 classes 0.990000 0.060000 1.050000 ( 1.176519) | |
# Calling methods ... 0.920000 0.000000 0.920000 ( 0.926232) | |
# + 5000 classes 0.770000 0.040000 0.810000 ( 0.796057) | |
# Calling methods ... 0.910000 0.000000 0.910000 ( 0.924063) | |
# + 5000 classes 1.100000 0.040000 1.140000 ( 1.125203) | |
# Calling methods ... 0.930000 0.000000 0.930000 ( 0.940422) | |
# + 5000 classes 0.930000 0.040000 0.970000 ( 0.969951) | |
# Calling methods ... 1.480000 0.010000 1.490000 ( 1.487894) | |
# + 5000 classes 0.720000 0.080000 0.800000 ( 0.805329) | |
# Calling methods ... 1.220000 0.000000 1.220000 ( 1.215931) | |
# + 5000 classes 1.560000 0.030000 1.590000 ( 1.598290) | |
# Calling methods ... 1.230000 0.010000 1.240000 ( 1.234221) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment