[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

x==1 vs 1==x

Gavin Kistner

6/20/2005 1:15:00 PM

I'm against _premature_ optimization in theory, but believe that a
certain innate knowledge of what is and what is not efficient is
important for making reasonable choices in the first place.

To that end, when I had to write code to handle exactly one case out
of many, where I knew that the operator would be #==, I thought I'd
test case versus if/elsif. As I expected, the case statement
performed worse (thought not as much as I expected).

On a whim, I also tested comparing x == 1 separate from 1 == x. Even
when x was a Fixnum, the latter was surprisingly and significantly
slower. Can anyone explain the following results?

8
Fixnum
Rehearsal ---------------------------------------------
case 1.500000 0.020000 1.520000 ( 2.249505)
if x==n 0.930000 0.020000 0.950000 ( 1.332420)
if n==x 1.330000 0.020000 1.350000 ( 1.914666)
------------------------------------ total: 3.820000sec

user system total real
case 1.510000 0.020000 1.530000 ( 2.343995)
if x==n 0.920000 0.020000 0.940000 ( 1.277303)
if n==x 1.340000 0.020000 1.360000 ( 1.937022)


require 'benchmark'

n = 100_000
x = rand( 10 )
p x, x.class
Benchmark.bmbm(10){ |x|
x.report('case'){
n.times{
case x
when 0 : 0
when 1 : 1
when 2 : 2
when 3 : 3
when 4 : 4
when 5 : 5
when 6 : 6
when 7 : 7
when 8 : 8
else 9
end
}
}
x.report('if x==n'){
n.times{
if x==0
0
elsif x==1
1
elsif x==2
2
elsif x==3
3
elsif x==4
4
elsif x==5
5
elsif x==6
6
elsif x==7
7
elsif x==8
8
else
9
end
}
}

x.report('if n==x'){
n.times{
if 0==x
0
elsif 1==x
1
elsif 2==x
2
elsif 3==x
3
elsif 4==x
4
elsif 5==x
5
elsif 6==x
6
elsif 7==x
7
elsif 8==x
8
else
9
end
}
}
}

--
(-, /\ \/ / /\/

18 Answers

Robert Klemme

6/20/2005 1:23:00 PM

0

Gavin Kistner wrote:
> I'm against _premature_ optimization in theory, but believe that a
> certain innate knowledge of what is and what is not efficient is
> important for making reasonable choices in the first place.
>
> To that end, when I had to write code to handle exactly one case out
> of many, where I knew that the operator would be #==, I thought I'd
> test case versus if/elsif. As I expected, the case statement
> performed worse (thought not as much as I expected).
>
> On a whim, I also tested comparing x == 1 separate from 1 == x. Even
> when x was a Fixnum, the latter was surprisingly and significantly
> slower. Can anyone explain the following results?

Yes, probably: you have something else in x than you expect. x is really
the benchmark instance and not some Fixnum. :-)

Kind regards

robert

>
> 8
> Fixnum
> Rehearsal ---------------------------------------------
> case 1.500000 0.020000 1.520000 ( 2.249505)
> if x==n 0.930000 0.020000 0.950000 ( 1.332420)
> if n==x 1.330000 0.020000 1.350000 ( 1.914666)
> ------------------------------------ total: 3.820000sec
>
> user system total real
> case 1.510000 0.020000 1.530000 ( 2.343995)
> if x==n 0.920000 0.020000 0.940000 ( 1.277303)
> if n==x 1.340000 0.020000 1.360000 ( 1.937022)
>
>
> require 'benchmark'
>
> n = 100_000
> x = rand( 10 )
> p x, x.class
> Benchmark.bmbm(10){ |x|
> x.report('case'){
> n.times{
> case x
> when 0 : 0
> when 1 : 1
> when 2 : 2
> when 3 : 3
> when 4 : 4
> when 5 : 5
> when 6 : 6
> when 7 : 7
> when 8 : 8
> else 9
> end
> }
> }
> x.report('if x==n'){
> n.times{
> if x==0
> 0
> elsif x==1
> 1
> elsif x==2
> 2
> elsif x==3
> 3
> elsif x==4
> 4
> elsif x==5
> 5
> elsif x==6
> 6
> elsif x==7
> 7
> elsif x==8
> 8
> else
> 9
> end
> }
> }
>
> x.report('if n==x'){
> n.times{
> if 0==x
> 0
> elsif 1==x
> 1
> elsif 2==x
> 2
> elsif 3==x
> 3
> elsif 4==x
> 4
> elsif 5==x
> 5
> elsif 6==x
> 6
> elsif 7==x
> 7
> elsif 8==x
> 8
> else
> 9
> end
> }
> }
> }

ts

6/20/2005 1:24:00 PM

0

>>>>> "G" == Gavin Kistner <gavin@refinery.com> writes:

G> p x, x.class

uln% diff -u b.rb~ b.rb
--- b.rb~ 2005-06-20 15:16:51.990598152 +0200
+++ b.rb 2005-06-20 15:17:40.826174016 +0200
@@ -3,8 +3,8 @@
n = 100_000
x = rand( 10 )
p x, x.class
-Benchmark.bmbm(10){ |x|
- x.report('case'){
+Benchmark.bmbm(10){ |xx|
+ xx.report('case'){
n.times{
case x
when 0 : 0
@@ -20,7 +20,7 @@
end
}
}
- x.report('if x==n'){
+ xx.report('if x==n'){
n.times{
if x==0
0
@@ -46,7 +46,7 @@
}
}

- x.report('if n==x'){
+ xx.report('if n==x'){
n.times{
if 0==x
0
uln%

uln% ruby b.rb
7
Fixnum
Rehearsal ---------------------------------------------
case 0.170000 0.000000 0.170000 ( 0.179179)
if x==n 0.190000 0.010000 0.200000 ( 0.194086)
if n==x 0.190000 0.000000 0.190000 ( 0.191561)
------------------------------------ total: 0.560000sec

user system total real
case 0.160000 0.020000 0.180000 ( 0.180628)
if x==n 0.190000 0.010000 0.200000 ( 0.195471)
if n==x 0.190000 0.010000 0.200000 ( 0.193239)
uln%



Guy Decoux


Gavin Kistner

6/20/2005 1:31:00 PM

0

On Jun 20, 2005, at 7:23 AM, ts wrote:
> -Benchmark.bmbm(10){ |x|
> +Benchmark.bmbm(10){ |xx|

rofl

Oops. Thanks :)

threeve.org

6/20/2005 1:46:00 PM

0

On 6/20/05, Gavin Kistner <gavin@refinery.com> wrote:
> On Jun 20, 2005, at 7:23 AM, ts wrote:
> > -Benchmark.bmbm(10){ |x|
> > +Benchmark.bmbm(10){ |xx|
>
> rofl
>
> Oops. Thanks :)
>

Even though it turns out there is no performance benefit to 1 == x
over x == 1, I find it desirable to write the former anyway. If you
accidentally write x = 1 instead of x == 1, it can take a long time to
figure out your bug. But if you write 1 = x instead of 1 == x, you
get a syntax error, and can immediately correct the mistake.


Jason


Peter Hickman

6/20/2005 2:05:00 PM

0

Jason Foreman wrote:

>Even though it turns out there is no performance benefit to 1 == x
>over x == 1, I find it desirable to write the former anyway. If you
>accidentally write x = 1 instead of x == 1, it can take a long time to
>figure out your bug. But if you write 1 = x instead of 1 == x, you
>get a syntax error, and can immediately correct the mistake.
>
>Jason
>
Although I can see a that writing 1 == x makes to catch 1 = x errors
makes a lot of sense it just doesn't read correctly to me. After all it
is the variable (reference) x that we are talking about, I would expect
to see it to be more prominently in the sentence, so to speak.

Just as I would prefer to read 1 <= x and x <= 100 over 1 <= x and 100 >
x. But then again I would prefer the icon idiom of 1 <= x <= 100.

I wonder if this relates to the grammar of your natural language (with
the subject, object, verb ordering).



Florian Groß

6/20/2005 2:13:00 PM

0

Nikolai Weibull

6/20/2005 2:21:00 PM

0

Jason Foreman wrote:

> Even though it turns out there is no performance benefit to 1 == x
> over x == 1, I find it desirable to write the former anyway. If you
> accidentally write x = 1 instead of x == 1, it can take a long time to
> figure out your bug. But if you write 1 = x instead of 1 == x, you
> get a syntax error, and can immediately correct the mistake.

% ruby
if x = 1; end
-:1: warning: found = in conditional, should be ==

So please don't write your code as if it was 1980 and you were using a C
compiler,
nikolai

--
Nikolai Weibull: now available free of charge at http:/...!
Born in Chicago, IL USA; currently residing in Gothenburg, Sweden.
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}


threeve.org

6/20/2005 2:24:00 PM

0

On 6/20/05, Florian Groß <florgro@gmail.com> wrote:
> Jason Foreman wrote:
>
> > If you accidentally write x = 1 instead of x == 1, it can take a long
> > time to figure out your bug.
>
> C:\Dokumente und Einstellungen\flgr>ruby
> foo = 10
> if foo = 10 then
> puts "Hello World!"
> end
> -:2: warning: found = in conditional, should be ==
> ^Z
> Hello World!
>
> I found out about my bug before I was even done giving Ruby the full
> application code. ;)
>
>
>

Nice. I didn't realize it gave that warning! :)

However:

$ ruby
x=2
case x
when x=1: p 'one'
when x==2: p 'two'
else p 'whoops!'
end
^D
"whoops!"


Michael Campbell

6/20/2005 2:33:00 PM

0

On 6/20/05, Nikolai Weibull
<mailing-lists.ruby-talk@rawuncut.elitemail.org> wrote:
> Jason Foreman wrote:
>
> > Even though it turns out there is no performance benefit to 1 == x
> > over x == 1, I find it desirable to write the former anyway. If you
> > accidentally write x = 1 instead of x == 1, it can take a long time to
> > figure out your bug. But if you write 1 = x instead of 1 == x, you
> > get a syntax error, and can immediately correct the mistake.
>
> % ruby
> if x = 1; end
> -:1: warning: found = in conditional, should be ==
>
> So please don't write your code as if it was 1980 and you were using a C
> compiler,
> nikolai

Amen. Even C compilers catch this sort of thing now; there's no need
for this logic-bending construct anymore.


Robert Klemme

6/20/2005 2:54:00 PM

0

Jason Foreman wrote:
> On 6/20/05, Florian Groß <florgro@gmail.com> wrote:
>> Jason Foreman wrote:
>>
>>> If you accidentally write x = 1 instead of x == 1, it can take a
>>> long time to figure out your bug.
>>
>> C:\Dokumente und Einstellungen\flgr>ruby
>> foo = 10
>> if foo = 10 then
>> puts "Hello World!"
>> end
>> -:2: warning: found = in conditional, should be ==
>> ^Z
>> Hello World!
>>
>> I found out about my bug before I was even done giving Ruby the full
>> application code. ;)
>>
>>
>>
>
> Nice. I didn't realize it gave that warning! :)
>
> However:
>
> $ ruby
> x=2
> case x
> when x=1: p 'one'
> when x==2: p 'two'
> else p 'whoops!'
> end
> ^D
> "whoops!"

Do you suggest to add a warning if there is an expression after "case"
*and* at least a single boolean expression after "when"? Note that the
correct form of what you did is this:

x=2
case
when x==1: p 'one'
when x==2: p 'two'
else p 'whoops!'
end

Kind regards

robert