我有一個哈希表:哪個Ruby語句更高效?
hash = Hash.new(0)
hash[:key] = hash[:key] + 1 # Line 1
hash[:key] += 1 # Line 2
線1和線2做同樣的事情。看起來像第1行需要通過鍵兩次查詢散列,而第2行只有一次。真的嗎?或者他們實際上是一樣的?
我有一個哈希表:哪個Ruby語句更高效?
hash = Hash.new(0)
hash[:key] = hash[:key] + 1 # Line 1
hash[:key] += 1 # Line 2
線1和線2做同樣的事情。看起來像第1行需要通過鍵兩次查詢散列,而第2行只有一次。真的嗎?或者他們實際上是一樣的?
我創建了一個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
是略勝一籌。
第二個是習慣性的做法。它更高效。
雖然你說的第二種方法是比較習慣的,但我不確定說「它更有效率」意味着它是:) – edwardsmatt
我在測試中被問及這個問題。那天晚上,我寫了一個腳本,測量了表現。它稍微好一些。 :) – Hrishi
@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)
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))
同樣,你看到的是,調節器和吸氣劑調用一次。
查看Ruby內置的['Benchmark'模塊](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html)。 – maerics