Two alleged coding best-practices

B

Ben_

Hello,

I was reading "IBM WebSphere V5.0 Performance, Scalability, and High
Availability" redbook, when the following assertions hit my mind:

(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"

(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

There is no explanation as about why it would provide with better
performance.

Can you fill the gap ?

Thanks.

Ben.
 
P

pete kirkham

Ben_ said:
(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"
This will be the case where a value is set:
int i;
if (test) {
i = 1;
} else {
i = 0;
}
foo(i);
Will cause one extra istore and one extra iload to be generated than
foo( (test ? 1 : 0) );
ie ? can be used to replace an explicit local variable with a stack
variable.
(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

iterating 0 to (n-1) (n is 10000000):
15 lstore_1
16 iconst_0
17 istore 8
19 goto 25
22 iinc 8 1
25 iload 8
27 ldc #3 <Integer 10000000> ; integer value loaded on every iteration
29 if_icmplt 22
iterating (n-1) to 0:
71 ldc #6 <Integer 9999999>
73 istore 9
75 goto 81
78 iinc 9 -1
81 iload 9
83 ifgt 78 ; comparison >0 single byte opertation

In this case (n-1)->0 is 7ms faster on my machine. If n is a variable,
field, method call etc the difference will vary.

Pete
 
A

Adam Maass

Ben_ said:
Hello,

I was reading "IBM WebSphere V5.0 Performance, Scalability, and High
Availability" redbook, when the following assertions hit my mind:

(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"

The ternary operator results in a single assignment operator, rather than
the two that would result from an if-else structure. Fewer opcodes.
(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

Comparison against 0 can be better optimized than comparison against
arbitrary n. Possibly fewer opcodes, but compare-against-0 is (usually) a
faster operation than compare-against-arbitary-int.

There is no explanation as about why it would provide with better
performance.

Can you fill the gap ?


These are both minor, minor optimizations and I would scream bloody hell at
a programmer who used either of them for peformance reasons without first
proving that there is a performance problem to begin with, and that the code
written in this manner helps improve the problem.

Having said that, I *like* the ternary operator for simple if-else
assignments; it's often more clear:

Compare:

if(cond)
{
str = "one";
}
else
{
str = "two";
}


Against:

str = cond ? "one" : "two";


Fewer lines of code, and it focuses attention on the assignment, rather than
the if structure. Note that this is *not* a performance argument for the
ternary operator.

YMMV.

-- Adam Maass
 
R

Roedy Green

(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"

(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

For 1, the problem would be a not-too-bright compiler.

For 2 the reason is hardware has special instructions to compare with
0. When you count down the end point is a compare with 0. When you
count up, the end point is a compare with N.

If you screw up the loop so that you compare your end point with 1 or
-1 instead, you won't get the tiny speed boost.

For similar reasons is faster to say > 0 rather than >= 1
 
M

Miguel De Anda

Ben_ said:
Hello,

I was reading "IBM WebSphere V5.0 Performance, Scalability, and High
Availability" redbook, when the following assertions hit my mind:

(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"

If you compare:

t = (a) ? a : b;

with this:

if (a)
t = a;
else
t = b;

Then the first solution is definately better. The only reason that I see is
because the compile has to consider other things inside either of the cases.
For example, your code could just as easily have been:

if (a) {
t = a;
a = b;
} else {
t = b;
b = a;
}

I guess its just easier to optimize the ternary operator.

(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

Maybe because in assembly, a loop is normally done like this...

mov cx, 10
lC:
.... stuff to loop through in here ....
loop lC


This is probably faster than using using something else since the cx
register was designed for loops. I doubt that java actually takes advantage
of this though.


There is no explanation as about why it would provide with better
performance.

Can you fill the gap ?

Thanks.

Ben.

I'm now entirely sure though, so don't answer a test question with my
answer.
 
T

Tobias Oed

Bent said:
I don't see this. In both cases, someCondition() is called first, then
either getA() or getB() is called, and finally getThing() is called.

<Complete newbie on p.~200 of Just java>

Ok now you got me confused. I just read that java always evaluates
expressions from left to right. So the ternary way would start out by
evaluating getThing().field then someCondition(). The if/else starts with
someCondition(), then getThing().field. Or what?

<\newbie>
Tobias.
 
X

xarax

Roedy Green said:
For 1, the problem would be a not-too-bright compiler.

Exactly. It's not a JVM issue, but rather it's how the
source is compiled to bytecode.
For 2 the reason is hardware has special instructions to compare with
0. When you count down the end point is a compare with 0. When you
count up, the end point is a compare with N.

As others have already said, there is a bytecode instruction
for comparing with zero that is faster than comparing with
some other constant.
If you screw up the loop so that you compare your end point with 1 or
-1 instead, you won't get the tiny speed boost.

As such, don't sweat the miniscule, negligible details like
this until there is a significantly measureable performance
issue with the overall algorithm.
For similar reasons is faster to say > 0 rather than >= 1

Again, this is a not-too-bright compiler that is not
noticing the edge condition when an integer comparison
(n >= 1) could be optimized to (n > 0), or (n > -1) is
really (n >= 0).
 
E

Eric Sosman

Roedy said:
For 1, the problem would be a not-too-bright compiler.

Is a Java compiler allowed to be that bright?

getThing().field = someCondition() ? getA() : getB();

will produce a result different from

if (someCondition())
getThing().field = getA();
else
getThing().field = getB();

if both getThing and someCondition throw exceptions. Is
the compiler permitted to change the order -- and perhaps
even the identity -- of the exceptions?
 
J

John C. Bollinger

Tobias said:
Bent C Dalager wrote:




<Complete newbie on p.~200 of Just java>

Ok now you got me confused. I just read that java always evaluates
expressions from left to right. So the ternary way would start out by
evaluating getThing().field then someCondition(). The if/else starts with
someCondition(), then getThing().field. Or what?

<\newbie>

Shame on you, Brent. Stop confusing the newbies. :)

In this case the newbie appears to have it right. (As did Eric Sosman.)
From the JLS (the important part is the first bullet point):

=====

15.26.1 Simple Assignment Operator =
A compile-time error occurs if the type of the right-hand operand cannot
be converted to the type of the variable by assignment conversion (§5.2).

At run time, the expression is evaluated in one of two ways. If the
left-hand operand expression is not an array access expression, then
three steps are required:

* First, the left-hand operand is evaluated to produce a variable.
If this evaluation completes abruptly, then the assignment expression
completes abruptly for the same reason; the right-hand operand is not
evaluated and no assignment occurs.
* Otherwise, the right-hand operand is evaluated. If this
evaluation completes abruptly, then the assignment expression completes
abruptly for the same reason and no assignment occurs.
* Otherwise, the value of the right-hand operand is converted to
the type of the left-hand variable, is subjected to value set conversion
(§5.1.8) to the appropriate standard value set (not an extended-exponent
value set), and the result of the conversion is stored into the variable.

[...]

=====


Thus, yes, the method invocation on the left-hand side of the assignment
in the ternary case occurs before any of those on the right-hand side,
and if it throws an exception then the right-hand side is not evaluated
at all.


John Bollinger
(e-mail address removed)
 
P

pete kirkham

Tobias said:
Ok now you got me confused. I just read that java always evaluates
expressions from left to right. So the ternary way would start out by
evaluating getThing().field then someCondition(). The if/else starts with
someCondition(), then getThing().field. Or what?

<\newbie>
Tobias.

That is correct:

class IfOrder {
....
public static void main (String[] args) {
String s;

s = "Ternary operator";

getThing().field = someCondition() ? getA() : getB();

s = "If version";

if (someCondition())
getThing().field = getA();
else
getThing().field = getB();
}
}

javac IfOrder.java
javap -c IfOrder

-->

0 ldc #7 <String "_Ternary operator form_">
2 astore_1
3 invokestatic #8 <Method IfOrder getThing()>
6 invokestatic #9 <Method boolean someCondition()>
9 ifeq 18
12 invokestatic #10 <Method int getA()>
15 goto 21
18 invokestatic #11 <Method int getB()>
21 putfield #12 <Field int field>
24 ldc #13 <String "_If/Else form_">
26 astore_1
27 invokestatic #9 <Method boolean someCondition()>
30 ifeq 45
33 invokestatic #8 <Method IfOrder getThing()>
36 invokestatic #10 <Method int getA()>
39 putfield #12 <Field int field>
42 goto 54
45 invokestatic #8 <Method IfOrder getThing()>
48 invokestatic #11 <Method int getB()>
51 putfield #12 <Field int field>
54 return

bytecodes @3 and 6 call getThing before someCondition for the ternary
operator form.

bytecodes @27 and (33 or 45) call someCondition before getThing for the
if/else form.

Pete
 
B

Bent C Dalager

Shame on you, Brent. Stop confusing the newbies. :)

In this case the newbie appears to have it right. (As did Eric Sosman.)
From the JLS (the important part is the first bullet point):

Interesting. In that case, I second Eric Sosman's assertion that a
compiler couldn't just optimize any old trivial if/else block into the
same as the conditional operator.

Cheers
Bent D
 
J

Jon A. Cruz

xarax said:
Exactly. It's not a JVM issue, but rather it's how the
source is compiled to bytecode.

I'd have to disagree.

As others have already said, there is a bytecode instruction
for comparing with zero that is faster than comparing with
some other constant.


Remember... once bytecodes go into a JVM, they might mutate into
something completely unexpected. This very much applies if you go into
something like a hotspot VM or a Transmeta chip with a Java layer (as
some infer was planned for the new Amiga before it was killed).
 
D

Dale King

Hello,

I was reading "IBM WebSphere V5.0 Performance, Scalability, and High
Availability" redbook, when the following assertions hit my mind:

(1) "use of ? : for a conditional check instead of if-then provides better
performance for most JVMs"

(2) "When iterating n items, iterating from n-1 to 0 instead of 1 to is
quicker for most JVMs"

There is no explanation as about why it would provide with better
performance.

Can you fill the gap ?

To summarize my feelings and what others have posted on this sort of
thing. It is true that these tweaks may speed up some code by a very
small amount. With the a new VM they may slow it down.

But they definitely should not be labelled as "Best Practices". You can
store the away in your performance bag of tricks if some day you need to
increase performance. You certainly should not start with them. Code for
readability first.
 
B

Bruce Lewis

Interesting. In that case, I second Eric Sosman's assertion that a
compiler couldn't just optimize any old trivial if/else block into the
same as the conditional operator.

Yes, but if the left-hand side of the assignment cannot throw exceptions
and is free of side effects, then such an optimization could be done.

Nonetheless, I think the ? : syntax is clearer in such cases, so I
wouldn't rate such an optimization as at all important.

--
"Notwithstanding fervent argument that patent protection is essential
for the growth of the software industry, commentators have noted
that `this industry is growing by leaps and bounds without it.'"
-- US Supreme Court Justice John Paul Stevens, March 3, 1981.
I rarely read mail sent to (e-mail address removed)
 
M

Manish Jethani

Bruce said:
Yes, but if the left-hand side of the assignment cannot throw exceptions
and is free of side effects, then such an optimization could be done.

But it would be very difficult to prove that the LHS doesn't
throw exceptions and it doesn't have side-effects. Unless,

Thing getThing()
{
return this.thing;
}

Even in this case, the compiler isn't supposed to assume that
the implementation of getThing() isn't going to change. IIRC
the only thing the compiler can resolve at compile time is a
compile-time constant. Java compilers don't even inline method
calls, etc.

It's possible for a JIT compiler though.

-Manish
 
B

Bent C Dalager

But it would be very difficult to prove that the LHS doesn't
throw exceptions and it doesn't have side-effects. Unless,

If the LHS isn't a method call, you can start making sure (you could
perhaps make sure for a method call if it was to a method in your own
class). You may have to rule out anything that could be null though -
I'm not entirely sure when exactly NullPointerException gets thrown
when the LHS is null but it wouldn't be unreasonably have it happen as
soon as you see the equivalent of "null.field = " regardless of what
would follow on the RHS.

So if you write

Thing thing = new Thing();
thing.field = ...;

then the compiler could probably assume that thing will never be null
and allow an optimization. But if you write

Thing thing = thingFactory.makeMeAThing();
thing.field = ...;

then it could probably not.

Cheers
Bent D
 
N

Neomorph

That depends on the declaration of the variable, see below.
If the LHS isn't a method call, you can start making sure (you could
perhaps make sure for a method call if it was to a method in your own
class). You may have to rule out anything that could be null though -
I'm not entirely sure when exactly NullPointerException gets thrown
when the LHS is null but it wouldn't be unreasonably have it happen as
soon as you see the equivalent of "null.field = " regardless of what
would follow on the RHS.

So if you write

Thing thing = new Thing();
thing.field = ...;

then the compiler could probably assume that thing will never be null
and allow an optimization.

Especially since an Exception is thrown on the 'new' when you run out of
memory or the constructor throw an Exception (i.e. IllegalArgumentException
for example).
But if you write

Thing thing = thingFactory.makeMeAThing();
thing.field = ...;

then it could probably not.

When field is defined as being static, then the result of thing being null
does not matter either. No NullPointerException will be thrown on the dot
access, since the Class will be accessed statically.

Although for a variable called 'field' it is highly unlikely that it is
declared static ;-)
Cheers
Bent D

Cheers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top