2012-01-13 104 views
3

在我最近花了一些時間的Ruby項目中,我一直在計算兩個大字符串的交集。與整數比較相比,爲什麼字符串比較如此之快?

從我認爲我理解的情況來看,我認爲比較整數而不是字符串會很有意義(所有這些字符串都被保存在數據庫中,我可以輕鬆地將它們交換爲id)

當我真的做了基準測試時,我最終發現了完全相反的結果。

首先我產生套850串,並套〜850大整數的:

r = Random.new 
w1 = (1..850).collect{|i| w="";(0..3).collect{|j| (rand*26 + 10).to_i.to_s(35)}.each{|l| w+=(l.to_s)};w}.to_set 
w2 = (1..850).collect{|i| w="";(0..3).collect{|j| (rand*26 + 10).to_i.to_s(35)}.each{|l| w+=(l.to_s)};w}.to_set 

i1 = (1..2000).collect{|i| (r.rand*1000).to_i**2}.to_set; 
i2 = (1..2000).collect{|i| (r.rand*1000).to_i**2}.to_set; 

然後我計時的比較:

t=Time.now;(0..1000).each {|i| w1 & w2};Time.now-t 
=> 0.301727 
t=Time.now;(0..1000).each {|i| i1 & i2};Time.now-t 
=> 0.70151 

,我認爲是瘋了!我一直認爲整數比較要快得多..

所以我想知道是否有人在堆棧世界知道任何關於爲什麼字符串比較在紅寶石的速度如此之快,我真的很感激聽到你的想法。

回答

7

交集操作的速度優異的比較似乎是由相交的元件的數量的影響。

您的整數創建代碼正在創建大量相交元素,可能是因爲它從較小集合(1000)中選擇了2000個條目。

在一個測試中,例如,i1中的857個條目中的755個在i2中被複制,但w1中的849個條目中僅有2個被複制到了w2中。

當我運行一個簡單的改變:

755.times {|x| w2 << w1.to_a[x]} 

(傾倒755項成被稱爲是在W1,W2,),我的系統上的研究結果表明琴絃組操作要更接近等價整數運算。

我原來的結果爲:

1.9.2p180 :006 > t=Time.now;(0..1000).each {|i| w1 & w2};Time.now-t 
=> 1.020355 
1.9.2p180 :007 > t=Time.now;(0..1000).each {|i| i1 & i2};Time.now-t 
=> 2.057535 

我使兩套套在交叉元件方面更相似後的結果,經由:

1.9.2p180 :051 > 755.times {|x| w2 << w1.to_a[x]} 
1.9.2p180 :052 > w2 = w2.to_a[-849..-1].to_set 

爲:

1.9.2p180 :053 > t=Time.now;(0..1000).each {|i| w1 & w2};Time.now-t 
=> 2.014967 
1.9.2p180 :054 > t=Time.now;(0..1000).each {|i| i1 & i2};Time.now-t 
=> 2.037542 
1.9.2p180 :055 > [i1.length, i2.length, w1.length, w2.length, (i1 & i2).length, (w1 & w2).length] 
=> [857, 884, 849, 849, 755, 754] 

我希望能幫到一些;這兩個時間點在我認爲是系統中其他事情可能導致差異的誤差範圍內。對於這個長度的字符串,它們本質上是相等的。

+0

偉大的答案..寫得好,描述性強。謝謝您的幫助。 :] – BananaNeil 2012-01-13 12:12:52

3

速度慢的原因是因爲沒有獲得儘可能多的匹配項。需要花費時間的是建立交叉的新數組,而不是實際的匹配本身。