Skip to content

Instantly share code, notes, and snippets.

@jage
Last active November 17, 2016 09:46
Show Gist options
  • Save jage/b0d3c397b5b46de421b537cbe41219f7 to your computer and use it in GitHub Desktop.
Save jage/b0d3c397b5b46de421b537cbe41219f7 to your computer and use it in GitHub Desktop.
Benchmark how to look up a class from string in Ruby

Benchmark how to look up a class from string in Ruby

Rescue NameError or ask if the constant is defined first?

Tested in Ruby 2.3 on OS X

$ bundle
...
$ bundle exec ruby benchmark.rb
Warming up --------------------------------------
undefined const with rescue
                        98.256k i/100ms
undefined const by asking first
                        26.705k i/100ms
Calculating -------------------------------------
undefined const with rescue
                          1.787M (± 2.7%) i/s -      8.941M in   5.008211s
undefined const by asking first
                        337.107k (± 3.0%) i/s -      1.709M in   5.074571s

Comparison:
undefined const with rescue:  1786652.0 i/s
undefined const by asking first:   337106.6 i/s - 5.30x  slower

Warming up --------------------------------------
defined const with rescue
                        88.743k i/100ms
defined const by asking first
                       117.461k i/100ms
Calculating -------------------------------------
defined const with rescue
                          1.442M (± 2.9%) i/s -      7.277M in   5.050590s
defined const by asking first
                          2.453M (± 3.6%) i/s -     12.333M in   5.034416s

Comparison:
defined const by asking first:  2453319.7 i/s
defined const with rescue:  1442062.0 i/s - 1.70x  slower
require "benchmark/ips"
class ForBenchmark1; end
class ForBenchmark2; end
def get_const_by_asking_first(const_name)
Kernel.const_defined?(const_name) && Kernel.const_get(const_name)
end
def get_const_with_rescue(const_name)
Kernel.const_get(const_name)
rescue NameError # Makes it very hard to discover typos in code
end
# Ensure behavior before benchmarking
raise "Fail!" unless ForBenchmark1 == get_const_by_asking_first("ForBenchmark1")
raise "Fail!" unless ForBenchmark2 == get_const_with_rescue("ForBenchmark2")
raise "Fail!" if get_const_by_asking_first("Undefined1")
raise "Fail!" if get_const_with_rescue("Undefined2")
# Benchmark with undefined constants
Benchmark.ips do |x|
x.report("undefined const with rescue") do
get_const_by_asking_first("Undefined1")
end
x.report("undefined const by asking first") do
get_const_with_rescue("Undefined2")
end
x.compare!
end
# Benchmark with defined constants
Benchmark.ips do |x|
x.report("defined const with rescue") do
get_const_by_asking_first("ForBenchmark1")
end
x.report("defined const by asking first") do
get_const_with_rescue("ForBenchmark2")
end
x.compare!
end
source "https://rubygems.org"
gem "benchmark-ips"
GEM
remote: https://rubygems.org/
specs:
benchmark-ips (2.7.2)
PLATFORMS
ruby
DEPENDENCIES
benchmark-ips
BUNDLED WITH
1.13.3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment