代码之家  ›  专栏  ›  技术社区  ›  Gdeglin

何时在RubyonRails中使用备忘录

  •  23
  • Gdeglin  · 技术社区  · 15 年前

    2008年7月中旬,将备忘录添加到Rails核心。下面是用法的演示 here .

    This blog post

    对于可能具有巨大性能影响的内容,除了提供一个简单的教程之外,似乎没有其他资源。


    下面是一个例子: http://github.com/rails/rails/blob/1182658e767d2db4a46faed35f0b1075c5dd9a88/actionpack/lib/action_view/template.rb .

    3 回复  |  直到 7 年前
        1
  •  34
  •   danneu    12 年前

    我认为许多Rails开发人员并不完全了解Memonization的功能和工作原理。我见过它应用于返回延迟加载集合(如Sequel dataset)的方法,或者应用于不带参数但基于实例变量计算某些内容的方法。在第一种情况下,回忆录只不过是开销,而在第二种情况下,它是令人讨厌且难以追踪的bug的来源。

    • 返回的值只是计算起来有点贵。那一定是 非常
    • 返回值是或可能是延迟加载的

    还有其他一些情况下,记忆是不合适的,比如上面的问题和答案,但我认为这三种情况并不明显。

    最后一项可能是最重要的:记忆根据方法的参数缓存结果,如果方法看起来像这样,则无法记忆:

    def unmemoizable1(name)
      "%s was here %s" % name, Time.now.strftime('%Y-%m-%d')
    end
    
    def unmemoizable2
      find_by_shoe_size(@size)
    end
    

    然而,这两种方法都可以重写,以利用记忆化(尽管在这两种情况下,由于其他原因,显然不应该这样做):

    def unmemoizable1(name)
      memoizable1(name, Time.now.strftime('%Y-%m-%d'))
    end
    
    def memoizable1(name, time)
      "#{name} was here #{time}"
    end
    memoize :memoizable1
    
    def unmemoizable2
      memoizable2(@size)
    end
    
    def memoizable2(size)
      find_by_shoe_size(size)
    end
    memoize :memoizable2
    

    (假设 find_by_shoe_size 没有或依赖于任何副作用)

        2
  •  10
  •   rud    15 年前

    当一个方法从多个表中获取数据,并在返回结果对象之前执行一些计算,并且该方法多次出现在请求中时,记忆可能是有意义的。

        3
  •  2
  •   Luke W    13 年前

    也许我的经验是一个很好的例子,说明什么时候不应该使用memoize。在我的订单模型中,我记录了两个简单的计算结果,即订单小计、订单税;以及模型对象,即订单、最近使用的信用卡。在后一种情况下,当记忆一个返回CreditCard对象的方法时,我在尝试更新记忆对象上的属性时会出现“冻结哈希”错误。订单#最近的#信用卡#用过的#冻结?当方法被记忆时返回true,这当然不是我想要的。

    我的收获很简单:对返回简单数据类型(整数、浮点等)的昂贵操作使用memoize,但在返回复杂对象时不使用memoize