红宝石的记忆,效率

时间:2014-10-25 10:35:36

标签: ruby memoization

这个问题主要是关于Ruby内部的,速度可以通过一个简单的基准来衡量。

在ruby中记忆返回值的最有效方法是什么?

我总是记住以下值:

def method
  @value ||= calculate_value
end

但是因为它在技术上扩展到:

@value = @value || calculate_value

我想知道每次重新执行相同作业的效率。

这会更好吗?

def method
  @value ? @value : (@value = calculate_value)
end

此外,它是否会在不同的口译员中发生变化? MRI,Rubinius等

3 个答案:

答案 0 :(得分:9)

你的例子

@value ||= calculate_value

相当于

@value || @value = calculate_value

等同于

@value = @value || calculate_value

因此答案是:它非常有效。每次都不会重新分配。

答案 1 :(得分:0)

@spickermann,@ tompave,很抱歉发布它作为答案,但我需要代码格式化来发布不同用例的基准测试结果。看起来显式方式是最快的@a || @a = calculated_value

> n = 10000000;
> a = 1;
> puts Benchmark.measure { n.times { a ||= 1 } }
  0.570000   0.000000   0.570000 (  0.569977)
> puts Benchmark.measure { n.times { a ? a : a = 1 } }
  0.560000   0.000000   0.560000 (  0.562855)
> puts Benchmark.measure { n.times { a || a = 1 } }
  0.530000   0.000000   0.530000 (  0.532715)
> @a = 1;
> puts Benchmark.measure { n.times { @a ||= 1 } }
  0.870000   0.000000   0.870000 (  0.869489)
> puts Benchmark.measure { n.times { @a ? @a : @a = 1 } }
  0.670000   0.000000   0.670000 (  0.668910)
> puts Benchmark.measure { n.times { @a || @a = 1 } }
  0.610000   0.000000   0.610000 (  0.613978)

ruby​​ 2.1.2p95(2014-05-08修订版45877)[x86_64-darwin13.0]

从结果的角度来看,所有3种符号的行为都相同,但从性能的角度来看,最后一种是禁食的。不幸的是,这都是经验性的,我不能在这里链接任何ruby源代码。

答案 2 :(得分:0)

我认为||=... = ... || ...之间的任何差异都应该是微妙的。

或许,一种更有效的方法是在设置值时切换方法。这种切换只发生一次,从那时起,方法调用只是对变量的引用,所以它应该很快,并且随着调用方法的次数的增加,优势也会增加。

def method
  alias method memoized_value
  @value ||= calculate_value
end

def memoized_value; @value end

这假设calculate_value总是返回一个真值,并且代码中没有其他部分可以修改该值,这样一旦调用method,变量的值仍然是真的。