2012-08-29 47 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和字符串文字的一部分。)您會介紹的重複越少越好。

正如你所看到的,答案相互矛盾,所以你必須瞭解你所做的決定的背景,並正確權衡各個因素,找出哪一個最好。