2012-08-29 49 views
-2

我在过去的许多日子里有一个问题,即在用Ruby编写代码时,线性代码是否比迭代更快,更可取?迭代比线性代码慢吗?哪一个更好?

让我举个例子。还有就是代码写在两种不同的方式相同的功能块:

方法1:

['dog', 'cat', 'tiger'].each do |pet_name| 
    puts "I have many pets, one of them is #{pet_name}." 
end 

方式2:

puts "I have many pets, one of them is dog." 
puts "I have many pets, one of them is cat." 
puts "I have many pets, one of them is tiger." 

所以,我想知道哪一个更好,最好?根据我的观点,我认为第二名将花费更少的时间和记忆。但我想确认一下。

+2

这个问题属于StackOverflow,它已经被询问和回答。 –

+0

对于给出的例子它可能不重要。你能举出一个真实世界的例子,这个问题可能有意义吗? – Caleb

回答

3

顺序逻辑速度更快(请参阅下面的基准),但它几乎从不重要。应该始终选择更清晰和更易维护的代码。只有一个显示需要为程序员导致一个停止优化并开始为机器优化。通过演示,我的意思是测量 - 你跑了它,发现它太慢了。

第二个示例违反了DRY (Don't Repeat Yourself)原则,是一个小问题。


require 'benchmark' 

LOOPS = 100000 

Benchmark.bm(10) do |x| 
    x.report('iteration') do 
    LOOPS.times do 
     ['dog', 'cat', 'tiger'].each do |pet_name| 
     "I have many pets, one of them is #{pet_name}." 
     end 
    end 
    end 
    x.report('sequence') do 
    LOOPS.times do 
     "I have many pets, one of them is dog." 
     "I have many pets, one of them is cat." 
     "I have many pets, one of them is tiger." 
    end 
    end 
end 

# =>     user  system  total  real 
# => iteration 0.200000 0.000000 0.200000 ( 0.202054) 
# => sequence  0.010000 0.000000 0.010000 ( 0.012195) 
0

严格来说,是的,在迭代中会涉及一个开销。将使用您使用的任何语言(尽管有些使用编译器技巧来减少这种情况)。由于迭代成本以及构建您定义的数组,您的代码的第一个版本运行速度可以忽略不计。另外,建立字符串可能会增加另一小部分成本。

话虽这么说,这是你必须非常挑剔的注意,甚至关心任何有关这这样一个微小的差别。这是微不足道的。尝试自己衡量它,你不会注意到一个显着的差异。

我不准备为某种方法写这样的10,000行,对吗?我发现迭代看起来更清晰,特别是对于非平凡的代码,并且在可读性和干净的代码方面通常更可取。更不用说它更多DRY

1

在这两种情况下,所花的时间运行的实际Ruby代码将是由它需要打印的文本到屏幕上的时间完全占主导地位。记住:控制台输出是真的很慢。痛苦地缓慢。由于在这两种情况下,代码都会在屏幕上打印相同数量的文本(实际上,其文本为文本),因此可能会或可能不会存在的任何微小的性能差异将会在噪声中丢失。

我认为:第二个将花费更少的时间和内存。

不要想。看。

这里有一个疯狂的想法:如果你想知道哪一个运行速度更快,运行它们,看看哪一个跑得快!

+1

+1“不要想。看。“证据总是胜过猜测。 –

0

总是有成本调用一个函数,创建一个数组或创建循环。但是这是编程语言建了,所以回答你的问题:也许是的,第二个代码会更快,纳秒。但第一个代码更一般,你永远不知道什么时候你会买一个新的宠物。这更有用,也许有人会给你的宠物名单,你会想谈谈他们?一般来说,第二个代码的速度并不快,但首先是更好,更好。

0

我知道你的例子是非常简单的,不太可能在现实世界中发生,但把它从字面上:

第一个例子将创建中间对象(字符串和数组),所以你可能会说,其实它将需要更多的记忆。然而,这些对象稍后会被垃圾回收,所以你会回忆起你的记忆。 (如果您定义了符号数组,则不会出现这种情况,因为符号不是垃圾收集的)。

它也更快,因为它不需要在每次迭代过程中从数组中取内部对象。但是这种差异如果明显不明显并且不应该考虑在内。这里应该考虑的是可读性。

如果你是一个性能怪胎,你可能应该定义你的方法没有括号括住参数,因为这会导致由Ruby解释器创建的更小的分析树。

# slower 
def meth(arg) 
end 

# faster 
def meth arg 
end 

但是考虑到它的一个合理的理由当然是愚蠢的。

编辑:如果你正在寻找一个良好的Ruby风格指南检查:https://github.com/bbatsov/ruby-style-guide

+0

非常感谢@Michal额外的知识(括号和非括号的表现) – RAJ

0

如果这两个选项之一显然更好,因此最好,语言不会提供这两个选项。一如既往,这取决于具体情况。您应该询问的问题包括:

  • 哪个解决方案更具可读性? (对于习惯性的Ruby程序员来说,第一个就是。)可读性越高越好。
  • 哪个解决方案更快? (你只能通过测量来确定这一点,小心使用一个现实的例子 - 只有三只动物的时差可能无法可靠地测量。)越快越好。
  • “展开”更惯用的版本引入了多少重复? (在这种情况下,不是很多 - puts和字符串文字的一部分。)您会介绍的重复越少越好。

正如你所看到的,答案相互矛盾,所以你必须了解你所做的决定的背景,并正确权衡各个因素,找出哪一个最好。