Last active
December 20, 2015 21:39
-
-
Save zacksiri/6199461 to your computer and use it in GitHub Desktop.
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 AgeGroup < Struct.new(:categories) | |
# def | |
# Hash[*AGE_CATEGORIES.keys | |
# .map { |r| r.map { |v| | |
# [v, AGE_CATEGORIES.select | |
# { |k, val| | |
# k.include?(v) | |
# }.values.first] | |
# } }.flatten].freeze | |
# end | |
def calculate_table | |
Hash[*categories.keys.map{ |r| expand_range(r) }.flatten] | |
end | |
def expand_range(range) | |
range.map { |n| make_age_array(n) } | |
end | |
def make_age_array(age) | |
[age, find_match_for(age)] | |
end | |
def find_match_for(age) | |
categories.detect { |k, val| k.include?(age) }.last | |
end | |
end | |
class User < Struct.new(:age) | |
AGE_CATEGORIES = { (0..9) => :child, (10..18) => :teenager, | |
(19..28) => :young, (29..50) => :adult, | |
(50..120) => :senoir }.freeze | |
COMPUTED_CATEGORIES = AgeGroup.new(AGE_CATEGORIES).calculate_table | |
def if_category | |
age = self.age | |
if age < 10 then :child | |
elsif age < 18 then :teenager | |
elsif age < 24 then :young | |
elsif age < 54 then :adult | |
elsif age < 100 then :senior | |
else :deity | |
end | |
end | |
def case_category | |
case age | |
when 0..9 then :child | |
when 10..18 then :teenager | |
when 19..28 then :young | |
when 29..50 then :adult | |
when 50..100 then :senoir | |
else :deity | |
end | |
end | |
def lookup_category_uncached | |
age = self.age | |
AGE_CATEGORIES.detect { |k, v| k.include?(age) }.last | |
end | |
def lookup_cached | |
COMPUTED_CATEGORIES[age] | |
end | |
end | |
Benchmark.bm(15) do |x| | |
x.report("if") { | |
10000000.times do | |
user = User.new(Random.rand(100)) | |
user.if_category | |
end | |
} | |
x.report("case") { | |
10000000.times do | |
user = User.new(Random.rand(100)) | |
user.case_category | |
end | |
} | |
x.report("lookup") { | |
10000000.times do | |
user = User.new(Random.rand(100)) | |
user.lookup_category_uncached | |
end | |
} | |
x.report("lookup_cached") { | |
10000000.times do | |
user = User.new(Random.rand(100)) | |
user.lookup_cached | |
end | |
} | |
end |
lookup_category_uncached
does too much. Could be even more optimized if changing the categories hash into an array, so detect doesn't create an intermediate array. This makes it twice as fast.
def lookup_category_uncached
age = self.age
AGE_CATEGORIES.detect { |k, _| k.include?(age) }.last
end
Yeah I was just discussin this with @scomma
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you're measuring different things. if_category creates a lot of string objects while lookup_cached returns symbols. Also you should create a temp variable for age in the if_category speed things up.