24

2008年7月中旬に、メモ化がRailsコアに追加されました。使用法のデモンストレーションはここにあります。

メソッドをメモ化するタイミングと、それぞれのパフォーマンスへの影響について、良い例を見つけることができませんでした。たとえば、このブログ投稿は、メモ化をまったく使用すべきではないことを示唆しています。

パフォーマンスに多大な影響を与える可能性のあるものについては、簡単なチュートリアルを提供する以上のリソースはほとんどないようです。

自分のプロジェクトでメモ化が使用されているのを見た人はいますか?メソッドのメモ化を検討する要因は何ですか?


自分でさらに調査したところ、Railsコア内でメモ化がかなりの回数使用されていることがわかりました。

次に例を示します:http://github.com/rails/rails/blob/1182658e767d2db4a46faed35f0b1075c5dd9a88/actionpack/lib/action_view/template.rb

この使用法は、メモ化がパフォーマンスに悪影響を与える可能性があるという上記のブログ投稿の結果に反しているようです。

4

3 に答える 3

34

多くの Rails 開発者は、メモ化が何をどのように行うのかを完全には理解していないと思います。遅延ロードされたコレクション (Sequel データセットなど) を返すメソッドに適用されたり、引数を取らずにインスタンス変数に基づいて何かを計算するメソッドに適用されたりするのを見てきました。前者の場合、メモ化は単なるオーバーヘッドであり、後者の場合は厄介で追跡が困難なバグの原因となります。

次の場合はメモ化を適用しません

  • 戻り値の計算には、わずかにコストがかかります。メモ化する価値があるためには、非常に高価で、さらに最適化できない必要があります。
  • 戻り値は遅延ロードされているか、遅延ロードされる可能性があります
  • メソッドは純粋な関数ではありません。つまり、同じ引数に対してまったく同じ値を返すことが保証されており、引数を使用してその作業を行うか、他の純粋な関数のみを使用します。インスタンス変数を使用するか、インスタンス変数を使用するメソッドを呼び出すと、メソッドは同じ引数に対して異なる結果を返す可能性があります。

上記の質問や回答のように、メモ化が適切でない状況は他にもありますが、これらはそれほど明白ではないと私が思う3つです。

最後の項目はおそらく最も重要です。メモ化は、メソッドへの引数に基づいて結果をキャッシュします。メソッドが次のように見える場合、メモ化することはできません。

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

def unmemoizable2
  find_by_shoe_size(@size)
end

ただし、どちらもメモ化を利用するように書き直すことができます (ただし、これら 2 つのケースでは、他の理由で行うべきではないことは明らかです)。

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(副作用がない、または依存していないと仮定して)

秘訣は、メソッドから純粋な関数を抽出し、代わりにメモ化を適用することです。

于 2009-12-04T14:15:04.707 に答える
10

メソッドが複数のテーブルからデータをフェッチし、結果のオブジェクトを返す前にいくつかの計算を実行し、このメソッドがリクエストで複数回使用される場合、メモ化は理にかなっています。

クエリ キャッシングもアクティブであることを忘れないでください。そのため、純粋なデータベース フェッチではなく、Ruby 内で計算を実行するメソッドのみを memoize してください。

于 2009-03-30T08:22:56.847 に答える
2

おそらく、私の経験は、メモ化を使用しない場合の良い例です。私の Order モデルでは、単純な計算結果、つまり Order#subtotal と Order#tax の両方をメモしていました。モデル オブジェクト、つまり Order#most_recent_credit_card_used と同様です。後者では、CreditCard オブジェクトを返すメソッドをメモ化するときに、メモ化されたオブジェクトの属性を更新しようとすると、「凍結ハッシュ」エラーが発生します。注文#most_recent_credit_card_used.frozen? メソッドがメモ化されたときに true を返しましたが、これはもちろん意図したものではありません。

単純なデータ型 (整数、浮動小数点数など) を返す高価な操作には memoize を使用しますが、 ActiveRecord モデルなどの複雑なオブジェクトを返す場合は memoize を使用しないでください。これらのオブジェクトをメモリ内で更新する場合。

于 2011-04-04T21:46:14.743 に答える