2012-11-11 73 views
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的原則,我有類。

但是有一個問題,如果我處理幾乎所有的列和調用匿名函數,它是如此之慢。 (匿名功能被稱爲大約10 000次,我知道,這是相當多的,但它不能這麼慢)頁面正在加載大約50秒。

問題在哪裏?你有什麼建議?

+0

你有沒有把它命名?你爲什麼確定它是關於lambda表達式的,而不是關於內部的代碼或你的類正在做什麼? – Anton

+0

當我對調用lambdas發表評論時,它會將頁面加載時間從50秒減少到2秒。 –

+0

但你爲什麼認爲這是'lambda'而不是本地化,'date_uzp'調用(這是兩次BTW),'helper_method',甚至是ERB? –

回答

0

匿名函數在這裏並不慢。這絕對是該功能的內容緩慢。

我最喜歡的分析工具是ruby-prof,MiniProfiler,並把內置的Benchmark.measure

初步猜測是:

  • 爲O運行(N)時間昂貴的操作,因爲這是真正容易得到操縱表時
  • 日期解析到。我的經驗是,一些日期解析功能是快速的,而另一些可能是狗慢(注意到使用date_uzp;不確定具體,只是指出它的可能性)。
  • 加載1000點的對象,那麼加載多個關聯(尤指具有多)每個對象上。加載多個activerecord對象可能非常慢,特別是如果它增加堆大小/開始觸發大量垃圾回收。

編輯

好吧,另外一種想法。 Lambdas(以及紅寶石中的所有塊)創建關閉以保持其上下文。也許你的lambdas的策略是防止大量的對象被垃圾收集?不過,我不確定如何通知您重構代碼。我知道如何在不關閉創建拉姆達的唯一方法是這樣的:

def foo 
    lambda {|row| helper_method row} 
end 

但一定是一個更好的方式來組織代碼。

+0

當我將lambda的內容更改爲{| row | },它仍然需要11秒加載。有什麼不同必須是錯的...... –

+0

好吧,又有一個想法(見答案編輯) – Woahdae