Skip to content

Instantly share code, notes, and snippets.

@zacksiri
Last active December 20, 2015 21:39
Show Gist options
  • Save zacksiri/6199461 to your computer and use it in GitHub Desktop.
Save zacksiri/6199461 to your computer and use it in GitHub Desktop.
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
@hasclass
Copy link

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.

  def if_category
    age = self.age
    if age < 10 then :child
    elsif age < 18 then :teenager
    elsif age < 28 then :young
    elsif age < 50 then :adult
    elsif age < 100 then :senor
    else 
      :deity
    end
  end

@hasclass
Copy link

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

@zacksiri
Copy link
Author

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