开发者

Different memoization techniques in Ruby

If you are a ruby programmer then you might have come across the hash block memoization pattern. For a simple example I present you the memoized version of the Fibonacci sequence:

fib_hash = Hash.new do |h,i|
  h[i] = 开发者_如何学编程h[i-1] + h[i-2]
end
# establish the base cases
fib_hash[1] = 1; fib_hash[2] = 1

Of course this is not the only way to create a memoized version of the Fibonacci sequence. You could also do the following:

@cache = {}; @cache[1] = 1; @cache[2] = 1
def memo_fib(n)
  @cache[n] ||= (memo_fib(n-1) + memo_fib(n-2))
end

Hopefully you see how the hash block memoization pattern maps to the second version which is much more common in many other languages. What I would like to know is if there is any difference between the two versions? I can't shake the feeling that the hash block version is more efficient but I can't really justify why.


A benchmark in MRI 1.8.7 yields:

  • Hash block: 0.44 seconds
  • Non hash block: 0.41 seconds

And in MRI 1.9.0:

  • Hash block: 0.24 seconds
  • Non hash block: 0.28 seconds

The benchmark is 100 iterations of computing the Fibonacci numbers from 1 through 1000, resetting the hash or cache at the start of each iteration.

Here's the benchmark for the hash block:

def reset_fib_hash                                                              
  @fib_hash = Hash.new do |h,i|
    h[i] = h[i-1] + h[i-2]
  end
  # establish the base cases                                                    
  @fib_hash[1] = 1; @fib_hash[2] = 1
end

start_time = Time.now
100.times do
  reset_fib_hash
  (1..1000).each do |i|
    @fib_hash[i]
  end
end
p Time.now - start_time

Here's the benchmark for the non hash block:

def reset_fib_hash
  @cache = {}; @cache[1] = 1; @cache[2] = 1
end

def memo_fib(n)
  @cache[n] ||= (memo_fib(n-1) + memo_fib(n-2))
end

start_time = Time.now
100.times do
  reset_fib_hash
  (1..1000).each do |i|
    memo_fib(i)
  end
end
p Time.now - start_time
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜