0

データベースから約1000行をロードしています。

テーブルを印刷するためのクラスがあります。ビューでは、ほぼ各列に対していくつかのルールを定義します。次に例を示します。

<% table.rules :date_uzp, lambda { |row| l row.date_uzp if row.date_uzp.present? } %>
<% table.rules :another_column, lambda { |row| helper_method row } %>

最後に、<%= table.print %> を呼び出すだけで、テーブルの html が生成されます。

テーブルを生成するための特別なクラスが必要なのはなぜですか? このプロジェクトでは、テーブルは非常に具体的であるため、DRY の原則に従うために、クラスを用意しています。

しかし、問題があります。ほとんどすべての列を処理して匿名関数を呼び出すと、非常に遅くなります。(anonym 関数は約 10,000 回呼び出されます。かなり多いですが、それほど遅くはありません) ページの読み込みに約 50 秒かかります。

どこに問題がありますか?何を指示してるんですか?

4

1 に答える 1

0

ここで遅いのは無名関数ではありません。遅いのは間違いなく関数の内容です。

私のお気に入りのプロファイリング ツールは、 ruby ​​-prof 、MiniProfiler、および組み込みの puts-ingBenchmark.measureです。

最初の推測は次のとおりです。

  • O(n) 2時間で実行される高価な操作。これは、テーブルを操作するときに簡単にアクセスできるためです。
  • 日付の解析。私の経験では、日付解析関数の中には高速なものもあれば、非常に遅いものもあります ( の使用に気づきましたdate_uzp。具体的にはわかりませんが、可能性として指摘しているだけです)。
  • 1000 個のオブジェクトをロードしてから、各オブジェクトに複数の関連付け (特に has-many) をロードします。多くのアクティブ レコード オブジェクトをロードすると、特にヒープ サイズが増加したり、大量のガベージ コレクションがトリガーされたりする場合、非常に遅くなる可能性があります。

編集

わかりました、別のアイデアです。ラムダ (および Ruby のすべてのブロック) は、そのコンテキストを維持するためにクロージャーを作成します。ラムダを使用した戦略によって、大量のオブジェクトがガベージ コレクションされるのを防いでいるのではないでしょうか? ただし、コードをリファクタリングするようにアドバイスする方法が正確にはわかりません。クロージャーなしでラムダを作成する方法を知っている唯一の方法は次のとおりです。

def foo
  lambda {|row| helper_method row}
end

しかし、コードを整理するためのより良い方法が必要です。

于 2012-11-11T22:16:30.187 に答える