.尝试 vs && 性能



假设我有一个来自SQL查询的传入值,如下所示:

grok = Foo.select(:foo_attr1, :foo_attr2).first

foo_attr2是一个可以为null的字段。现在假设我需要对输出做一些事情,如果它存在的话。

krug = grok.foo_attr2.try(:bar).try(:baz)
gnar = grok.foo_attr2 && grok.foo_attr2.bar.baz # Assumes bar will always return output that can be baz'd

这两种操作中哪一种更适合使用,为什么?

使用gnar = grok.foo_attr2 && grok.foo_attr2.bar.baz肯定会比使用Ruby的逻辑运算符更快。而try是由Rails引入的,并进行额外的if-else条件检查。发件人代码:

# File activesupport/lib/active_support/core_ext/object/try.rb, line 41
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    public_send(*a, &b) if respond_to?(a.first)
  end
end

好吧,这里有一个基准来展示我想说的:

class Object
  def try(*a, &b)
    if a.empty? && block_given?
      yield self
    else
      public_send(*a, &b) if respond_to?(a.first)
    end
  end
end
class Foo
  attr_reader :a
  def initialize(a = nil)
    @a = a    
  end
end
require "benchmark"

bar = Foo.new
baz = Foo.new(1)
n = 10000000
Benchmark.bm(40) do |x|
  x.report("try"){ n.times { bar.a.try(:class).try(:to_s) } }
  x.report("&& "){ n.times { baz.a && baz.a.class.to_s } }
end

结果是:

           user      system      total        real
try      10.800000  0.030000   10.830000  ( 10.829770)
&&        3.940000   0.010000   3.950000  (  3.944375)

最新更新