为什么调用许多匿名函数是如此之慢?

时间:2012-11-11 21:59:15

标签: ruby-on-rails performance optimization view lambda

从数据库中我加载了大约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 } %>

最后,我只是调用&lt;%= table.print%&gt;,然后为表生成html。

为什么我需要一个特殊的类来生成表格?表格在这个项目中非常具体,所以为了遵循DRY的原则,我可以上课......

但是有一个问题,如果我处理几乎所有的列并在它们上调用匿名函数,那就太慢了。 (匿名函数被称为大约10000次,我知道,它是相当多的但它不能这么慢)页面加载大约50s。

哪里有问题?你有什么建议?

1 个答案:

答案 0 :(得分:0)

匿名函数在这里并不慢。这绝对是功能的内容很慢。

我最喜欢的分析工具是ruby-profMiniProfiler,并且内置了Benchmark.measure

初步推测是:

  • 昂贵的操作在O(n) 2 时间运行,因为操作表时真的很容易进入
  • 解析日期。我的经验是,一些日期解析函数很快,而其他函数可能很慢(注意使用date_uzp;不确定它具体,只是指出它可能)。
  • 加载1000个对象,然后在每个对象上加载多个关联(esp has-many)。加载许多activerecord对象可能会非常慢,特别是如果它增加堆大小/开始触发大量垃圾回收。

修改

好的,另一个想法。 Lambdas(以及ruby中的所有块)创建闭包以维护其上下文。也许你使用lambdas的策略是阻止大量对象被垃圾收集?但是,我并不确定如何建议您重构代码。我知道如何在没有闭包的情况下创建lambda的唯一方法是:

def foo
  lambda {|row| helper_method row}
end

但必须有更好的方法来组织代码。