2012-01-13 152 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

速度慢的原因是因为没有获得尽可能多的匹配项。需要花费时间的是建立交叉的新数组,而不是实际的匹配本身。