Skip to content

Instantly share code, notes, and snippets.

@umanoda
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save umanoda/de73bcbc5a13a0aa91b3 to your computer and use it in GitHub Desktop.
Save umanoda/de73bcbc5a13a0aa91b3 to your computer and use it in GitHub Desktop.
Benchmark of WeakRef Cache
$ ruby weakref_cache.rb
user system total real
no_cache 0.000000 0.000000 0.000000 ( 0.000611)
weakref_cache 0.000000 0.000000 0.000000 ( 0.000349)
cache 0.000000 0.000000 0.000000 ( 0.000208)
require 'digest/sha1'
require "weakref"
class WeakCache
def initialize
@caches = {}
end
def [](key)
@caches[key]
end
def []=(key, value)
ref = WeakRef.new(value)
ObjectSpace.define_finalizer(value, WeakCache.ensure_cleanup(@caches, key, ref))
@caches[key] = ref
end
def self.ensure_cleanup(caches, key, ref)
proc{
caches.delete(key) if caches[key] == ref
}
end
end
class Dog
Info = Struct.new :name, :age, :sex, :strength
@@cache_basic_calc = {}
def initialize(name, breed="mix")
sex = calc_sex(name)
strength = calc_strength(breed) + calc_strength(name)
@info = Info.new name, 0, sex, strength
end
private
def basic_calc(str)
key = str.to_s.downcase
@@cache_basic_calc[key] ||=
Digest::SHA1.hexdigest(key).split(/[^0-9]/).inject(0){|sum, num| sum + num.to_i}
end
# @return [Symbol] 犬の性別 (:male or :female)
def calc_sex(str)
sex = basic_calc(str) % 2
sex.zero? ? :male : :female
end
# @return [Integer] 犬の強さ (0-255)
def calc_strength(str)
basic_calc(str) % 256
end
end
class DogTeam1
@@cache_dog = ::WeakCache.new
def initialize(breed, dog1, dog2, dog3, dog4, dog5)
@team = [
dog(dog1, breed),
dog(dog2, breed),
dog(dog3, breed),
dog(dog4, breed),
dog(dog5, breed),
]
end
private
def dog(name, breed)
Dog.new(name, breed)
end
end
class DogTeam2
@@cache_dog = ::WeakCache.new
def initialize(breed, dog1, dog2, dog3, dog4, dog5)
@team = [
dog(dog1, breed),
dog(dog2, breed),
dog(dog3, breed),
dog(dog4, breed),
dog(dog5, breed),
]
end
private
def dog(name, breed)
@@cache_dog[[name, breed]] ||= Dog.new(name, breed)
end
end
class DogTeam3
@@cache_dog = {}
def initialize(breed, dog1, dog2, dog3, dog4, dog5)
@team = [
dog(dog1, breed),
dog(dog2, breed),
dog(dog3, breed),
dog(dog4, breed),
dog(dog5, breed),
]
end
private
def dog(name, breed)
@@cache_dog[[name, breed]] ||= Dog.new(name, breed)
end
end
###################################
# Benchmark Test
###################################
require "benchmark"
Benchmark.bm(500) do |b|
b.report(:no_cache){
10.times{|n| DogTeam1.new("team", "won", "one", "nyao", "wan#{n}", "nyao#{n}") }
}
b.report(:weakref_cache){
10.times{|n| DogTeam2.new("team", "won", "one", "nyao", "wan#{n}", "nyao#{n}") }
}
b.report(:cache){
10.times{|n| DogTeam3.new("team", "won", "one", "nyao", "wan#{n}", "nyao#{n}") }
}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment