# Question on speed

**URL:** <https://www.ruby-forum.com/t/question-on-speed/65481>\
**Category:** Ruby\
**Created:** [August 18, 2006, 4:08pm UTC](https://www.ruby-forum.com/t/question-on-speed/65481 "2006-08-18T16:08:33Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![L7L7L7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/48db29/32.png) [@L7L7L7](https://www.ruby-forum.com/u/L7L7L7)\
**Post date:** [August 18, 2006, 4:08pm UTC](https://www.ruby-forum.com/t/question-on-speed/65481/1 "2006-08-18T16:08:33Z")

</div>

Based on the following snippet:

File.open(name).each { |line|  
case line  
when /not found/, /^[gBbTi]/  
next  
when /^S/  
# start or stop condition  
when /^I/  
# iteration indicator  
else  
# actual data  
end  
}

In the first when, (/not found/, /^[gBbTi]/) is there any benefit in  
setting up the statement in either of the following ways?

when /^[gBbTi]/, /not found/  
Put the short circuit one first (expected to happen more often than  
‘not found’)

OR

when /^g/, /^B/, /^b/, /^T/, /^i/, /not found/  
Separate each operation into it’s own portion of the test (ordered  
by expected frequency)

I guess this is really a question of ‘how does ruby handle the multiple  
arguments to a case statement?’.  
Are they taken in order or all compiled to a single expression before  
ever being evaluated?

Thanks for any insight.

---

<div class="post-metadata">

**Author:** ![L7L7L7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/48db29/32.png) [@L7L7L7](https://www.ruby-forum.com/u/L7L7L7)\
**Post date:** [August 18, 2006, 4:44pm UTC](https://www.ruby-forum.com/t/question-on-speed/65481/2 "2006-08-18T16:44:40Z")

</div>

On 18/08/06, L7 [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> In the first when, (/not found/, /^[gBbTi]/) is there any benefit in  
> setting up the statement in either of the following ways?

Ruby doesn’t compile the separate expressions: it sends ===(subject)  
to each argument in turn. They don’t have to be regular expressions,  
after all. Putting the more frequent match first is indeed quicker, as  
expected - but that’s an optimisation that can only be made with  
foreknowledge of the data set.

Separating each operation into its own argument is significantly  
slower due to the Ruby method call overhead. Knowing this, however, we  
can derive a further optimisation by combining the two regular  
expressions together: /^[gBbTi]|not found/

Paul.

PS: I did a bit of quick unscientific profiling to check. Here’s the  
code:

data = [  
“goat”,  
“Badger”,  
“bear”,  
“Tiger”,  
“ibis”,  
“not found”,  
“Start”,  
“Data goes here”  
] \* 10000

t0 = Time.now  
data.each do |line|  
case line  
when /not found/, /^[gBbTi]/  
next  
end  
end  
p Time.now - t0 # 0.236658

t0 = Time.now  
data.each do |line|  
case line  
when /^[gBbTi]/, /not found/  
next  
end  
end  
p Time.now - t0 # 0.176375

t0 = Time.now  
data.each do |line|  
case line  
when /^[gBbTi]|not found/  
next  
end  
end  
p Time.now - t0 # 0.145403

t0 = Time.now  
data.each do |line|  
case line  
when /^g/, /^B/, /^b/, /^T/, /^i/, /not found/  
next  
end  
end  
p Time.now - t0 # 0.299182

---

<div class="post-metadata">

**Author:** ![L7L7L7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/48db29/32.png) [@L7L7L7](https://www.ruby-forum.com/u/L7L7L7)\
**Post date:** [August 18, 2006, 5:17pm UTC](https://www.ruby-forum.com/t/question-on-speed/65481/3 "2006-08-18T17:17:47Z")

</div>

Paul B. wrote:

> Separating each operation into its own argument is significantly  
> “Badger”,  
> case line  
> next  
> end  
> p Time.now - t0 # 0.145403
> 
> t0 = Time.now  
> data.each do |line|  
> case line  
> when /^g/, /^B/, /^b/, /^T/, /^i/, /not found/  
> next  
> end  
> end  
> p Time.now - t0 # 0.299182

Thank you for the explanation and example (it’s plenty 'un’scientific  
for my needs).

---

<div class="post-metadata">

**Author:** ![L7L7L7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/48db29/32.png) [@L7L7L7](https://www.ruby-forum.com/u/L7L7L7)\
**Post date:** [August 18, 2006, 9:57pm UTC](https://www.ruby-forum.com/t/question-on-speed/65481/4 "2006-08-18T21:57:23Z")

</div>

Paul B. wrote:

> p Time.now - t0 # 0.236658

Shh. Don’t tell anyone, but there’s the benchmark module ‘bm’. Pickaxe  
has a good introduction on how to use it, and it prints pwetty result  
tables. And comes with a convenient method to do a dry and “real” run to  
let GC have a chance to kick in.

David V.
