2013-08-22 64 views
1

我有一個哈希表:哪個Ruby語句更高效?

hash = Hash.new(0) 

hash[:key] = hash[:key] + 1 # Line 1 
hash[:key] += 1    # Line 2 

線1和線2做同樣的事情。看起來像第1行需要通過鍵兩次查詢散列,而第2行只有一次。真的嗎?或者他們實際上是一樣的?

+2

查看Ruby內置的['Benchmark'模塊](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html)。 – maerics

回答

4

我創建了一個Ruby腳本的基準它

require 'benchmark' 

def my_case1() 
    @hash[:key] = @hash[:key] + 1 
end 

def my_case2() 
    @hash[:key] += 1 
end 

n = 10000000 
Benchmark.bm do |test| 
    test.report("case 1") { 
    @hash = Hash.new(1) 
    @hash[:key] = 0 
    n.times do; my_case1(); end 
    } 

    test.report("case 2") { 
    @hash = Hash.new(1) 
    @hash[:key] = 0 
    n.times do; my_case2(); end 
} 
end 

下面是結果

 user  system  total  real 
case 1 3.620000 0.080000 3.700000 ( 4.253319) 
case 2 3.560000 0.080000 3.640000 ( 4.178699) 

它看起來hash[:key] += 1是略勝一籌。

0

第二個是習慣性的做法。它更高效。

+0

雖然你說的第二種方法是比較習慣的,但我不確定說「它更有效率」意味着它是:) – edwardsmatt

+0

我在測試中被問及這個問題。那天晚上,我寫了一個腳本,測量了表現。它稍微好一些。 :) – Hrishi

1

@sza打我吧:)

這裏是我的榜樣irb會議:

> require 'benchmark' 
=> true 
> n = 10000000 
=> 10000000 
> Benchmark.bm do |x| 
> hash = Hash.new(0) 
> x.report("Case 1:") { n.times do; hash[:key] = hash[:key] + 1; end } 
> hash = Hash.new(0) 
> x.report("Case 2:") { n.times do; hash[:key] += 1; end } 
> end 
     user  system  total  real 
Case 1: 1.070000 0.000000 1.070000 ( 1.071366) 
Case 2: 1.040000 0.000000 1.040000 ( 1.043644) 
1

Ruby語言規範闡明瞭很清楚的評估簡稱索引賦值表達式的算法。它是這樣的:

primary_expression[indexing_argument_list] ω= expression 
# ω can be any operator, in this example, it is + 

爲(大約)評價像

o = primary_expression 
*l = indexing_argument_list 
v = o.[](*l) 
w = expression 
l << (v ω w) 
o.[]=(*l) 

特別是,你可以看到,無論是getter和setter方法將被調用一次。

你也可以看到,通過查看非正式脫糖:

hash[:key] += 1 

# is syntactic sugar for 

hash[:key] = hash[:key] + 1 

# which is syntactic sugar for 

hash.[]=(:key, hash.[](:key).+(1)) 

同樣,你看到的是,調節器和吸氣劑調用一次。