-2

过去很多天我有一个问题,在用 ruby​​ 编写代码时,线性代码是否比迭代更快、更可取?

让我举个例子。有一个相同功能的代码块以两种不同的方式编写:

方式一:

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

方式二:

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."

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

4

6 回答 6

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)
于 2012-08-29T11:11:35.723 回答
1

在这两种情况下,运行实际 Ruby 代码所花费的时间将完全由将文本打印到屏幕所花费的时间支配。记住:控制台输出很真的很慢。痛苦的慢。

由于在这两种情况下,代码都会在屏幕上打印相同数量的文本(实际上是相同的文本),因此任何可能存在或可能不存在的微小性能差异都会在噪音中消失。

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

不要想。看。

这是一个疯狂的想法:如果您想知道哪个跑得更快,请运行它们,看看哪个跑得更快!

于 2012-08-29T10:56:41.133 回答
0

如果这两个选项中的一个明显更好并因此更可取,那么该语言将不会同时提供这两个选项。与往常一样,这取决于具体情况。你应该问决定的问题包括

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

如您所见,答案相互矛盾,因此您必须了解您所做决定的背景并正确权衡因素以找出总体上最好的。

于 2012-08-29T11:01:20.597 回答
0

我意识到您的示例非常简化,在现实世界中不太可能发生,但从字面上理解:

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

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

如果你是一个性能狂,你可能应该定义你的方法,不要在参数周围加上括号,因为这会导致 Ruby 解释器创建的解析树更小。

# slower
def meth(arg)
end

# faster
def meth arg
end

但认为这是一个正当的理由当然是愚蠢的。

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

于 2012-08-29T11:03:34.790 回答
0

调用函数、创建数组或创建循环总是有成本的。然而,这就是编程语言的目的,所以回答你的问题:是的,第二个代码会更快,可能是纳秒。但第一个代码更笼统,你永远不知道什么时候会买一只新宠物。它更有用,也许有人会给你他们的宠物清单,你会想谈谈它们?一般来说,第二个代码更快,但第一个更好,更可取。

于 2012-08-29T10:58:21.880 回答
0

严格来说,是的,迭代涉及开销。您使用的任何语言都会有(尽管有些使用编译器技巧来减少这种情况)。由于迭代成本和构建您定义的数组的成本,您的代码的第一个版本将运行得更快一些。此外,弦乐建设可能还会增加一小部分成本。

话虽如此,这是一个如此微小的差异,你必须非常挑剔才能注意到,甚至关心其中的任何一个。这是微不足道的。尝试自己进行基准测试,您不会注意到显着差异。

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

于 2012-08-29T10:56:33.500 回答