【问题标题】:Does Ruby cache the result of a method that will evaluate to the same result?Ruby 是否缓存将评估为相同结果的方法的结果?
【发布时间】:2016-01-18 21:47:25
【问题描述】:

Ruby 是否会缓存方法的结果,以便在调用两次时不需要对其进行两次评估?

我在 Rails 中工作,例如,我可以执行以下操作,将传递到 Rails 控制器的参数的结果存储在一个变量中,如下所示:

def foo_bar_method
  case param[:foobar]
  when 'foo' then 'bar'
  when 'bar' then 'baz'
  else 'barbaz'
end

result = foo_bar_method
puts result
puts result

这样我只评估一次foo_bar_method。 Ruby 是否缓存此方法的结果(或者 Rails 是否这样做)?使用上面显示的代码是不是更快,还是下面的代码会产生相同的性能?

def foo_bar_method
  case param[:foobar]
  when 'foo' then 'bar'
  when 'bar' then 'baz'
  else 'barbaz'
end

puts foo_bar_method
puts foo_bar_method

【问题讨论】:

  • 它会缓存SQL查询,但我不认为上述方法的结果会被缓存。
  • 注意:为了做到这一点,Ruby 必须判断该方法是否是引用透明的,这相当于解决了 Halting Problem。

标签: ruby-on-rails ruby caching


【解决方案1】:

Ruby 不缓存方法结果,因为几乎没有任何 ruby​​ 函数可以称为纯函数,并且由于 ruby​​ 是动态的,编译器无法判断值是否发生变化。例如这个函数:

def four
  2 + 2
end

在时间上似乎是恒定的。好吧,如果您这样做,则不会:

class Fixnum
  def +(other)
    self * other - 3
  end
end  

嗯,显然这样做可能是你能做的最糟糕的事情,但事实是你可以做到。

在您的两个示例中,不会有可衡量的性能提升,但在许多情况下,这是编写代码的标准方式(执行一次并存储到变量)。

当你确定你正在处理一个总是产生相同结果的函数时,你可以使用这样的实例变量来缓存它:

def foo_bar_method
  @foo_bar_method ||= 
    case param[:foobar]
      when 'foo' then 'bar'
      when 'bar' then 'baz'
      else 'barbaz'
    end
end

假设这是您的控制器中的一个方法,可以安全地假设此值在控制器生命周期内不会改变(因为每个请求使用不同的控制器实例),因此缓存可能有意义,尤其是对于较重的计算。

【讨论】:

    【解决方案2】:

    Ruby 不会缓存方法的结果。如果你想自己做,你可以自己添加记忆。有很多方法可以做到这一点和几个宝石。只取决于您需要什么(即参数处理等)

    https://en.wikipedia.org/wiki/Memoization

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-25
      • 1970-01-01
      • 2015-11-03
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多