我想知道是什么让 if 比我的代码中的短路评估更快:
GC.disable
N = 5000
def x
j = nil
N.times {
if j
j << 'a'.freeze
else
j = ''
end
}
j
end
def y
j = nil
N.times {
j && j << 'a'.freeze || j = ''
}
j
end
t = Time.now
N.times { x }
p Time.now - t
sleep 0.1
t = Time.now
N.times { y }
p Time.now - t
无论我在没有额外 CPU 负载的情况下运行代码多少次,我都会得到:
3.826009846
4.137173916
或类似的东西。
整数也是一样,稍微修改一下代码,让j=nil,然后0,然后j加上+1。
是什么让方法 y 比方法 x 慢?
答案 0 :(得分:0)
根据评论更新。这是一种改进 x 方法的方法。 B 是您的方法,C 是改进版本,因为使用这种语法, && 的右侧永远不会被执行。 Benchmark 是标准的 Ruby 方式,它准确地执行该类旨在用于易于阅读文档的操作。要了解为什么不推荐使用 INT IDENTITY
,请参阅 this answer。此外,将迭代移至基准测试是很常见的,以免弄乱您的实际方法。
Time.now
结果:
require 'benchmark'
GC.disable
N=50000
class Foo
def a
j = nil
if j
j << 'a'.freeze
else
j = 'not nil'
end
j
end
def b
j = nil
j && j << 'a'.freeze || j = 'not nil'
j
end
def c
j = nil
j && (j << 'a' || j = 'j')
j
end
end
foo = Foo.new
foo.a
foo.b
foo.c
Benchmark.bmbm(10) do |x|
x.report(:a) { N.times {foo.a }}
puts "j is no longer nil, but it's a string #{foo.a} <- see"
x.report(:b) { N.times {foo.b }}
puts "j is equal to #{foo.b} which is a string, not nil"
x.report(:c) { N.times {foo.c }}
puts "look for j, nothing here *#{foo.c}* but emptiness"
end
puts "\n take 2\n"
Benchmark.bmbm(10) do |x|
x.report(:c) { N.times {foo.c }}
x.report(:a) { N.times {foo.a }}
x.report(:b) { N.times {foo.b }}
end