# Strange speeds

**URL:** <https://www.ruby-forum.com/t/strange-speeds/86780>\
**Category:** Ruby\
**Created:** [January 2, 2006, 10:15am UTC](https://www.ruby-forum.com/t/strange-speeds/86780 "2006-01-02T10:15:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 2, 2006, 10:15am UTC](https://www.ruby-forum.com/t/strange-speeds/86780/1 "2006-01-02T10:15:07Z")

</div>

Hello ruby people,  
I’ve tried to make some speed test in ruby to find out how fast is  
searching in hash (using has\_key?)

The results were OK but I discovered curious thing – when i generate  
big hash the speed is different when i unserialize (marshal.load) the  
same hash.

Unserialized Hash is 1.5x faster in has\_key? method. Tried it with  
GC.disable as well, results were same.

What am I missing?

Thanx for any ideas

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 2, 2006, 12:00pm UTC](https://www.ruby-forum.com/t/strange-speeds/86780/2 "2006-01-02T12:00:34Z")

</div>

kryglik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> What am I missing?
> 
> Thanx for any ideas

The first reason that comes to mind is different insertion order. But I  
hardly believe it could make such a big difference. Care to post your  
testing code?

Kind regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 2, 2006, 1:43pm UTC](https://www.ruby-forum.com/t/strange-speeds/86780/3 "2006-01-02T13:43:21Z")

</div>

Robert K. wrote:

> > GC.disable as well, results were same.
> 
> robert

Well, insertion order will be same, won’t be?

h = {}  
h\_slovo = []

if not true #HERE YOU SWITCH IF GENERATE/LOAD  
for x in 1…40\_000  
if x % 2000 == 0  
puts x  
end

```
     slovo = ""

     for z in 1..32
         slovo += (rand(25)+65).chr
     end

     if rand(10) == 3
         h_slovo << slovo
     end

     h.update slovo => rand(1_000_000)
     slovo = nil
 end

 f = File.new("hash.marshal","w+")
 f.puts(Marshal.dump(h))
 f.close

 f = File.new("hash1.marshal","w+")
 f.puts(Marshal.dump(h_slovo))
 f.close

```

else

```
 puts "loading hash"
 h = Marshal.load(File.open("hash.marshal","r"))
 puts "loading hash1"
 h_slovo = Marshal.load(File.open("hash1.marshal","r"))
 puts "done"

```

end

t1 = Time.now

for slovo1 in h\_slovo  
h.has\_key? h\_slovo  
end

t2 = Time.now

puts "hash: " + h.size.to\_s  
puts "hled: " + h\_slovo.size.to\_s  
puts t2-t1

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 2, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/strange-speeds/86780/4 "2006-01-02T17:15:33Z")

</div>

kryglik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > Unserialized Hash is 1.5x faster in has\_key? method. Tried it with  
> > > Kind regards
> > 
> > robert
> 
> Well, insertion order will be same, won’t be?

Not necessarily. If Marshal.dump uses the current order in the hash for  
writing then the insertion order during loading is likely to be  
different  
from the original insertion order.

> ```
> end
> puts "loading hash"
> 
> ```
> 
> end
> 
> t2 = Time.now
> 
> puts "hash: " + h.size.to\_s  
> puts "hled: " + h\_slovo.size.to\_s  
> puts t2-t1

Your time measurement is far too unprecise on a modern system. You’ll  
have  
to repeat lookups to get more accurate results. I get a difference  
between 5  
and 10 percent with the attached code - regardless of GC enabled or  
disabled. Strange though that the copy is always slower. This is an  
interesting issue.

Note, if you freeze keys lookups in the original hash are much faster  
because then hash keys are not copied on insertion (an optimisation of  
unfrozen Strings as hash keys), i.e., during lookup if the key is the  
same  
it’s also the same object which will be the first test - and of course  
this  
test is much faster than sequential comparison of characters.

Another note, a more realistic scenario would be if not 10% of all keys  
were  
used for lookup but if there also were keys that are not present in the  
hash.

Kind regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 3, 2006, 12:55am UTC](https://www.ruby-forum.com/t/strange-speeds/86780/5 "2006-01-03T00:55:24Z")

</div>

Hello  
thanx for nice script!

I find out that i got a little error :o) [see the ‘for’ cycle in  
benchmark part:  
for slovo1 in h\_slovo  
h.has\_key? h\_slovo (SHOULD NOT BE h\_slovo BUT slovo1)  
end

so when I run your script i got confused about speeds like 1-3s instead  
of my 60s. The difference between marshaled and generated was like 35s  
and 60s (10000 keys in 100.000 hash).

Still the mysteria continues – why the different speeds.

And also thanx for lecture of ruby optimization - not quite a guru (yet  
:-D).

Benchmark is a nice module 🙂

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 2, 2006, 5:15pm UTC](https://www.ruby-forum.com/t/strange-speeds/86780/6 "2006-01-02T17:15:41Z")

</div>

> > > > > “k” == kryglik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

k\> Well, insertion order will be same, won’t be?

This is not the same hash

moulon% cat b.rb  
#!/usr/bin/ruby  
h = {}  
32.times {|i| h[(rand(25)+65).chr] = i}  
File.open(“hash.marshal”,“w+”) {|f| f.puts(Marshal.dump(h)) }  
h1 = File.open(“hash.marshal”,“r”) {|f| Marshal.load(f) }  
puts h.keys.join(’ ‘)  
puts h1.keys.join(’ ')  
moulon%

moulon% ./b.rb  
V K W L A B M X C D O E F Q G R H I U  
K V A L W X M B C O D E Q F R G H I U  
moulon%

Guy Decoux

---

<div class="post-metadata">

**Author:** ![kryglik](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/d78d45/32.png) [@kryglik](https://www.ruby-forum.com/u/kryglik)\
**Post date:** [January 3, 2006, 2:06pm UTC](https://www.ruby-forum.com/t/strange-speeds/86780/7 "2006-01-03T14:06:29Z")

</div>

kryglik [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> instead of my 60s. The difference between marshaled and generated was  
> like 35s and 60s (10000 keys in 100.000 hash).

In this case it’s probably due to hash calculation for the hash you  
accidentally used as key.

> Still the mysteria continues – why the different speeds.

Yeah, I guess we would have to dive into the sources to find out…

> And also thanx for lecture of ruby optimization - not quite a guru  
> (yet :-D).

Take your time. 🙂

> Benchmark is a nice module 🙂

It really is!

Kind regards

```
robert

```
