Forum: Ruby Performance diffrence between ifs and case

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
forgottenwizard (Guest)
on 2007-07-29 05:15
(Received via mailing list)
What kind of diffrences are there, effectivly, between case and a series
of if statements, like in this:

if i="hi"
  puts "hi"
elsif i="bye"
  puts "bye"
else
  puts i
end

and

case i
  when hi
    puts "hi"
  when bye
    puts "bye"
else
  puts i
end
Phlip (Guest)
on 2007-07-29 05:30
(Received via mailing list)
forgottenwizard wrote:

> What kind of diffrences are there, effectivly, between case and a series
> of if statements, like in this:

Google for "premature optimization is the root of all evil".

Ruby is not the most performant language on the block, and both those
statements will resolve to a chain of conditionals. You need to devote
your
time to making clear readable code that's easy to upgrade. When the time
comes to speed it up, if you have unit tests, you can change it easily,
while profiling to see what's actually slow. Trying to guess what will
be
slow will only make you waste time writing complex code.

The most important resource to optimize is programmer time.
forgottenwizard (Guest)
on 2007-07-29 05:34
(Received via mailing list)
On 10:29 Sun 29 Jul     , Phlip wrote:
> comes to speed it up, if you have unit tests, you can change it easily,
>
Okay, to sum up what you said, not a damn thing? Thats all the answer I
needed, not an explination why I shouldn't bother to care how to do
things properly, or why I would not want to try and learn a little more
on the internals of a language.
Phlip (Guest)
on 2007-07-29 05:40
(Received via mailing list)
forgottenwizard wrote:

> Okay, to sum up what you said, not a damn thing? Thats all the answer I
> needed, not an explination why I shouldn't bother to care how to do
> things properly, or why I would not want to try and learn a little more
> on the internals of a language.

Ah, but I said it much more diplomatically than Tony Hoare and/or Don
Knuth
did!

Learn the internals of Ruby; they rock. However, optimization is a
sore-spot
around here, because the language is slower than molasses in January (in
the Norther Hemisphere).
John J. (Guest)
on 2007-07-29 05:54
(Received via mailing list)
Or, just write code using case, then code using if's
then test it.
Ruby has a testing facility in the standard library!
That's the quickest way to find out.
forgottenwizard (Guest)
on 2007-07-29 06:06
(Received via mailing list)
On 10:53 Sun 29 Jul     , John J. wrote:
> Or, just write code using case, then code using if's
> then test it.
> Ruby has a testing facility in the standard library!
> That's the quickest way to find out.
>

Is there any idea on which way the aforementioned systems will evolve,
or is that kind of a toss-up.

What I'm doing right now, it doesn't make much of a diff either way, so
I'll use case sinces its less typing...
Phlip (Guest)
on 2007-07-29 06:42
(Received via mailing list)
forgottenwizard wrote:

> Is there any idea on which way the aforementioned systems will evolve,
> or is that kind of a toss-up.

There's at least one attempt out there to write a compiler for Ruby.
That
requires a re-write, and while of course its goal is more performance,
the
exact resulting mix will indeed be a toss-up.

> What I'm doing right now, it doesn't make much of a diff either way, so
> I'll use case sinces its less typing...

So ... 'case' is more "DRY"?
Gregory B. (Guest)
on 2007-07-29 07:44
(Received via mailing list)
On 7/28/07, forgottenwizard <removed_email_address@domain.invalid> wrote:
> What kind of diffrences are there, effectivly, between case and a series
> of if statements, like in this:

Because of the way case works, it will depend on what you are trying to
do.
Use the benchmark standard library for your use case to find out which
is more efficient.
forgottenwizard (Guest)
on 2007-07-29 08:10
(Received via mailing list)
On 11:41 Sun 29 Jul     , Phlip wrote:
> >I'll use case sinces its less typing...
>
> So ... 'case' is more "DRY"?
>
It seems to me, that since I can't tell a real diffrence (I'll look into
the benchmarking bits later), I might as well use what seems the easiest
to expand as things go along.

Less to type in

case i
  when arg,a
  ...
  when arb,b
...

instead of
if i="arg" or i="a"

:)
Sean S. (Guest)
on 2007-07-29 11:43
Phlip wrote:
> forgottenwizard wrote:
>
>> What kind of diffrences are there, effectivly, between case and a series
>> of if statements, like in this:
>
> Google for "premature optimization is the root of all evil".

Classify as "nostrum-emitting moron."
John C. (Guest)
on 2007-07-30 01:58
(Received via mailing list)
On Sun, 29 Jul 2007, Sean S. wrote:

> Phlip wrote:
>> forgottenwizard wrote:
>>
>>> What kind of diffrences are there, effectivly, between case and a series
>>> of if statements, like in this:
>>
>> Google for "premature optimization is the root of all evil".
>
> Classify as "nostrum-emitting moron."

a) Phlip emits very valid and important nostrums.
b) Definitely not a moron, you'll miss some Good Stuff if you make that
mistake.
c) Once anyone actually benchmarks the difference and hence contributes
real data to the
    discussion....

   Write it up here...
      http://rubygarden.org/ruby/page/show/RubyOptimization
...the wiki page where I keep breadcrumbs of info for when desperation
requires me to shovel perfectly correct nostrums to one side and put in
a twist of
speed.

Speaking of which... Rubygarden seems to be slow..

Gah! Spammers have totally vandalized that page. Twice. Hmm. That's
probably
why it's so slow, probably a major spam attack...

I hate spammers. Really the complete scum of the earth. The Lambda the
Ultimate (excellent programming language design site)
http://lambda-the-ultimate.org crew have also been under attack.

Anyway, Ruby garden has nice review and revert facilities so it's fixed
now.

John C.                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : 
removed_email_address@domain.invalid
New Zealand
M. Edward (Ed) Borasky (Guest)
on 2007-07-30 02:56
(Received via mailing list)
John C. wrote:
> Speaking of which... Rubygarden seems to be slow..
>
> Gah! Spammers have totally vandalized that page. Twice. Hmm. That's
> probably
> why it's so slow, probably a major spam attack...
>
> I hate spammers. Really the complete scum of the earth. The Lambda the
> Ultimate (excellent programming language design site)
> http://lambda-the-ultimate.org crew have also been under attack.

Nobody is willing to do what it will take to eliminate spam (and for
that matter, junk snail mail), namely, tax it. :)
forgottenwizard (Guest)
on 2007-07-30 07:38
(Received via mailing list)
If you can come up with a way to tax spammers w/o causing problems for
normal traffic and fully eliminating spam, then by all means do so.
Personally, I'd prefer just find who is responsibe, and beat them to
within an inch of their lives and remove all their computer rights
permanently.
John C. (Guest)
on 2007-07-30 08:04
(Received via mailing list)
On Mon, 30 Jul 2007, forgottenwizard wrote:
> Personally, I'd prefer just find who is responsibe, and beat them to
> within an inch of their lives and remove all their computer rights
> permanently.

And once we've got rid of them...

..we can go after those who persist in extending tangential and off
topic threads... ;-D

Sorry, couldn't resist a good sharp leg pull.


John C.                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : 
removed_email_address@domain.invalid
New Zealand
Francis C. (Guest)
on 2007-07-30 08:48
(Received via mailing list)
On 7/28/07, forgottenwizard <removed_email_address@domain.invalid> wrote:
> end
> end
>
>
>

As you've written the code, the first example will probably run
noticeably
faster because it will never perform a comparison. The assignment in the
first if statement will always be true, and so the first branch will
always
be taken.

To answer a related question (but one that you didn't ask): case/when
uses
the === operator rather than  ==, which is typically used in if/when
constructions that (unlike yours) are intended to perform comparisons
rather
than assignments.

And perhaps surprisingly, === is extremely slow when applied to
arguments
that are Symbols. In those cases, I always use if/else.
forgottenwizard (Guest)
on 2007-07-30 09:11
(Received via mailing list)
On 13:47 Mon 30 Jul     , Francis C. wrote:
> >         puts i
> >         puts i
> To answer a related question (but one that you didn't ask): case/when uses
> the === operator rather than  ==, which is typically used in if/when
> constructions that (unlike yours) are intended to perform comparisons rather
> than assignments.
>
> And perhaps surprisingly, === is extremely slow when applied to arguments
> that are Symbols. In those cases, I always use if/else.

Actually, I'm going by the contents of ARGV[] with the actual program. I
ran across symbols just awhile ago looking through a few refrences, but
havn't messed with them any currently.

A more-or-less realistic example would be (just using case here):

case ARGV[9]
  when "hi", "H"
    puts "hi"
  when "bye, "B"
    puts "bye"
else
  puts ARGV[9]
end

Don't know if that makes a diff, but all this is pretty much passed down
through a single starting function as arguments to the function.
Alex Y. (Guest)
on 2007-07-30 12:03
(Received via mailing list)
John C. wrote:
>>
>> Classify as "nostrum-emitting moron."
>
> a) Phlip emits very valid and important nostrums.
> b) Definitely not a moron, you'll miss some Good Stuff if you make that
> mistake.
> c) Once anyone actually benchmarks the difference and hence contributes
> real data to the
>    discussion....
logic_benchmark.rb:

require 'benchmark'

def nop
end

def if_equiv_method(str)
   if "hi" === str
     nop
   elsif "bye" === str
     nop
   else
     nop
   end
end

def if_method(str)
   if str == "hi"
     nop
   elsif str == "bye"
     nop
   else
     nop
   end
end

def case_method(str)
   case str
   when "hi"
     nop
   when "bye"
     nop
   else
     nop
   end
end

strings = %w{hi bye foo}

Benchmark.bmbm(20) do |x|
   x.report("if"){for i in 0..1000000 do
if_method(strings[rand(strings.length)]) end }
   x.report("if_equiv"){for i in 0..1000000 do
if_equiv_method(strings[rand(strings.length)]) end }
   x.report("case"){for i in 0..1000000 do
case_method(strings[rand(strings.length)]) end }
end

Results:

C:\WINDOWS\system32\cmd.exe /c ruby logic_benchmark.rb
Rehearsal -------------------------------------------------------
if                    2.578000   0.000000   2.578000 (  2.610000)
if_equiv              2.797000   0.000000   2.797000 (  2.953000)
case                  2.625000   0.000000   2.625000 (  2.812000)
---------------------------------------------- total: 8.000000sec

                           user     system      total        real
if                    2.578000   0.000000   2.578000 (  2.625000)
if_equiv              2.781000   0.000000   2.781000 (  2.828000)
case                  2.625000   0.000000   2.625000 (  2.672000)

It's pretty marginal, and I did have them come out much closer on some
runs.

>
>   Write it up here...
>      http://rubygarden.org/ruby/page/show/RubyOptimization
> ...the wiki page where I keep breadcrumbs of info for when desperation
> requires me to shovel perfectly correct nostrums to one side and put in
> a twist of
> speed.
>
> Speaking of which... Rubygarden seems to be slow..
Too slow for me to write this up, as a matter of fact.
Robert D. (Guest)
on 2007-07-30 15:16
(Received via mailing list)
On 7/30/07, John C. <removed_email_address@domain.invalid> wrote:
> On Mon, 30 Jul 2007, forgottenwizard wrote:
> > Personally, I'd prefer just find who is responsibe, and beat them to
> > within an inch of their lives and remove all their computer rights
> > permanently.
>
> And once we've got rid of them...
>
> ..we can go after those who persist in extending tangential and off
> topic threads... ;-D
No, your logic is important as of course everybody of us will be the
single sole survivor on earth :(
>
> Sorry, couldn't resist a good sharp leg pull.
Which was well deserved.
Robert
Gregory B. (Guest)
on 2007-07-30 18:23
(Received via mailing list)
On 7/30/07, Alex Y. <removed_email_address@domain.invalid> wrote:

> Benchmark.bmbm(20) do |x|
>    x.report("if"){for i in 0..1000000 do

Yuck!

1000000.times do ... end
Alex Y. (Guest)
on 2007-07-30 19:03
(Received via mailing list)
Gregory B. wrote:
> On 7/30/07, Alex Y. <removed_email_address@domain.invalid> wrote:
>
>> Benchmark.bmbm(20) do |x|
>>    x.report("if"){for i in 0..1000000 do
>
> Yuck!
>
> 1000000.times do ... end
>
Meh.

require 'benchmark'

def nop
end

Benchmark.bmbm(20) do |x|
   x.report("range"){for i in 0..1000000 do nop end}
   x.report("times"){1000000.times do nop end}
end

Rehearsal -------------------------------------------------------
range                 0.578000   0.000000   0.578000 (  0.594000)
times                 0.531000   0.000000   0.531000 (  0.578000)
---------------------------------------------- total: 1.109000sec

                           user     system      total        real
range                 0.578000   0.000000   0.578000 (  0.594000)
times                 0.578000   0.000000   0.578000 (  0.578000)
James G. (Guest)
on 2007-07-30 19:19
(Received via mailing list)
On Jul 30, 2007, at 9:35 AM, Alex Y. wrote:

> Gregory B. wrote:
>> On 7/30/07, Alex Y. <removed_email_address@domain.invalid> wrote:
>>> Benchmark.bmbm(20) do |x|
>>>    x.report("if"){for i in 0..1000000 do
>> Yuck!
>> 1000000.times do ... end
> Meh.

It has nothing to do with timing.  It's about ugly verses pretty.  :)

James Edward G. II
John C. (Guest)
on 2007-07-31 01:12
(Received via mailing list)
On Mon, 30 Jul 2007, Alex Y. wrote:

>>   Write it up here...
>>      http://rubygarden.org/ruby/page/show/RubyOptimization
>> ...the wiki page where I keep breadcrumbs of info for when desperation
>> requires me to shovel perfectly correct nostrums to one side and put in a
>> twist of speed.
>>
>> Speaking of which... Rubygarden seems to be slow..
> Too slow for me to write this up, as a matter of fact.

http://rubygarden.org/Ruby/page/show/CaseIfBenchmark



John C.                             Phone : (64)(3) 358 6639
Tait Electronics                        Fax   : (64)(3) 359 4632
PO Box 1645 Christchurch                Email : 
removed_email_address@domain.invalid
New Zealand
Alex Y. (Guest)
on 2007-07-31 01:16
(Received via mailing list)
John C. wrote:
>
> http://rubygarden.org/Ruby/page/show/CaseIfBenchmark
>
Fab.  Thanks for that - I wouldn't have got round to it.
Paul M. (Guest)
on 2007-07-31 15:46
(Received via mailing list)
def nop
end


Benchmark.bmbm(20) do |x|
   x.report("range"){for i in 0..1000000 do nop end}
   x.report("times"){1000000.times do nop end}
   x.report("each"){(0..1000000).each do nop end}
end
------------------------------------------------
range     0.657000   0.000000   0.657000 (  0.656000)
times     0.609000   0.000000   0.609000 (  0.609000)
each      0.594000   0.000000   0.594000 (  0.594000)
----------------------------- total: 1.860000sec

         user     system      total        real
range     0.641000   0.000000   0.641000 (  0.640000)
times     0.594000   0.000000   0.594000 (  0.594000)
each      0.578000   0.000000   0.578000 (  0.594000)
Gregory B. (Guest)
on 2007-08-01 21:03
(Received via mailing list)
On 7/31/07, Paul <removed_email_address@domain.invalid> wrote:
> range     0.657000   0.000000   0.657000 (  0.656000)
> times     0.609000   0.000000   0.609000 (  0.609000)
> each      0.594000   0.000000   0.594000 (  0.594000)
> ----------------------------- total: 1.860000sec
>
>          user     system      total        real
> range     0.641000   0.000000   0.641000 (  0.640000)
> times     0.594000   0.000000   0.594000 (  0.594000)
> each      0.578000   0.000000   0.578000 (  0.594000)

I'll remember this next time I want to save 0.03 s per 1000000
iterations.

<groans>

My original point was that if you want to do something n times, use
n.times
:)
Alex Y. (Guest)
on 2007-08-01 22:14
(Received via mailing list)
Gregory B. wrote:
>> ------------------------------------------------
> I'll remember this next time I want to save 0.03 s per 1000000 iterations.
>
> <groans>
>
> My original point was that if you want to do something n times, use n.times
> :)
>
My point was going to be that the one place optimisation really matters
is in benchmark code - you only want to measure the effect you're
looking for - but I managed to shoot myself in the foot and prove
another point.  Don't assume, measure!  :-)
Kaldrenon (Guest)
on 2007-08-01 22:32
(Received via mailing list)
On Jul 29, 12:10 am, forgottenwizard <removed_email_address@domain.invalid>
wrote:
>
> :)

Just a thought from an iffer (cases are ugly in Java, so I just got
used to always iffing):

case i
  when arg,a
    ...
  when arb,b
    ...
end

isn't much different from

if [arg,a].include?( i )
  ...
elsif [arb,b].include?( i )
  ...
end

include? is possibly less efficient, though. Haven't benched it.
Gregory B. (Guest)
on 2007-08-01 22:33
(Received via mailing list)
On 8/1/07, Alex Y. <removed_email_address@domain.invalid> wrote:

> My point was going to be that the one place optimisation really matters
> is in benchmark code - you only want to measure the effect you're
> looking for - but I managed to shoot myself in the foot and prove
> another point.  Don't assume, measure!  :-)

If that's the case you shouldn't be making a nop() method call.
That's a *huge* part of what you're seeing there.
unknown (Guest)
on 2007-08-01 22:46
(Received via mailing list)
Hi --

On Thu, 2 Aug 2007, Alex Y. wrote:

>>> end
>>
> measure!  :-)
Even if one of the iterators (each or times) was much faster than the
other, as long as you use the same one every time you're controlling
for that.  You just wouldn't want to go back and forth.


David
Alex Y. (Guest)
on 2007-09-26 01:03
(Received via mailing list)
James Edward G. II wrote:
> It has nothing to do with timing.  It's about ugly verses pretty.  :)
To be perfectly honest, I had it fixed in my head that for...in... was
faster than N.times {} when I wrote the original code, and was just
trying to get rid of an unnecessary overhead.  Just shows what use
assumptions like that are...
This topic is locked and can not be replied to.