This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes Performance and the fly likes Performance issues in decision blocks Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Performance
Bookmark "Performance issues in decision blocks" Watch "Performance issues in decision blocks" New topic
Author

Performance issues in decision blocks

Ajith Kallambella
Sheriff

Joined: Mar 17, 2000
Posts: 5782
Is there a reason to belive a nested-if statement is inefficient compared to a switch-case?
Code block 1


Code block 1

Ofcourse, I am assuming I will be able to convert the if-evaluation to an equivalent switch-case evaluation.
Any thoughts?
TIA
Ajith


Open Group Certified Distinguished IT Architect. Open Group Certified Master IT Architect. Sun Certified Architect (SCEA).
Joe Paolangeli
Ranch Hand

Joined: Apr 05, 2000
Posts: 73
After reviewing Bill Brogden's Exam Cram book I found some performance info about the switch-case statement: "The JVM has bytecodes designed to speed this operation". So I think the switch-case statement may be faster but it may depend on how deeply the if-else statement is nested.
You are making an assumption about being able to convert an if-else statement to a switch-case statement. The switch-case statement can only support 32-bit or smaller primitive integer types. You cannot use long, float, double primitive types or objects such as String.
IMHO I think the switch-case statement is much easier to read than a deeply nested if-else statement. The only problem is the limitations mentioned above.
Hope this helps,
Joe
[This message has been edited by Joe Paolangeli (edited January 16, 2001).]
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
The answer partially depends on the layout of your switch statement. The compiler will use two different opcodes for switch statements depending on the organization of the cases. For example, it will use the lookupswitch opcode when there are no contiguous ranges of case values. This is the most ineficient in my tests. A straight if-else is faster than the lookupswitch switch block. However, if you group your case statements into contiguous ranges of switch values, it is the fastest of them all. Your code will get bigger though, because you have to code in dummy cases. In this case, the compiler generates the more efficient tableswitch opcode for faster performance.
Slowest:
switch (val)
{
case 10: return x;
case 1: return x;
case 12: return x;
case 17: return x;
case 5: return x;
case 20: return x;
}
Faster:
if (val == 10)
return x;
else if (val == 1)
return x;
else if (val == 12)
return x;
else if (val == 17)
return x;
else if (val == 5)
return x;
else if (val == 20)
return x;
Fastest:
switch (val)
{
case 1: return x;
case 2: break; //dummy
case 3: break; //dummy
case 4: break; //dummy
case 5: return x;
}
switch (val)
{
case 10: return x;
case 11: break; //dummy
case 12: return x;
}
etc...
Of course, you should always profile to be sure you are getting better performance on your JVM/JIT combination. Mileage can/will vary. I ran my tests on JDK 1.2.1.
Peter Haggar
------------------
author of: Practical Java


Senior Software Engineer, IBM
author of: Practical Java
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
Peter,
Why is that? Is it because using contiguous ranges, the compiler can calculate a jump, rather than hard wiring it? (Although that seems like it would only make it slower).
Are you basing the judgement only on opcodes? Do the different opcodes break down into different instructions on a given chip, possibly with different performance characteristics?
I know many processors today do branch prediction. Combined with JIT technology, would this ultimately render both options relatively equal in critical (i.e. often used) sections of code?
--Mark
hershey@vaultus.com
Peter Haggar
author
Ranch Hand

Joined: Jan 03, 2001
Posts: 106
Originally posted by Mark Herschberg:
Peter,
Why is that? Is it because using contiguous ranges, the compiler can calculate a jump, rather than hard wiring it? (Although that seems like it would only make it slower).

If there is a contiguous range, the tableswitch opcode can simply check to see if the value is within range, if not it can skip the entire switch. The lookupswitch checks each one, although less efficiently than an if-else.
Are you basing the judgement only on opcodes? Do the different opcodes break down into different instructions on a given chip, possibly with different performance characteristics?

This is quite possible and is why I put my warning in about your mileage could vary. It is also why I put the JVM I used for my tests. I would also caution anyone writing their code this way unless they have proven there is a performance problem and this fixes it. I give an optimizing Java code talk frequently and I show some tricks and various, arguably ugly, things. I always emphasize not to code this way normally, but keep these things up your sleeve in case you run into trouble with performance. Then you can try them out. However, always be sure to profile before and after because one technique may work on one hardware/JVM combo but not on another.
I know many processors today do branch prediction. Combined with JIT technology, would this ultimately render both options relatively equal in critical (i.e. often used) sections of code?

Again, possible which is why it is so important not to assume any optimization technique will yield the same result on different systems.
Good questions...
Peter Haggar
------------------
author of: Practical Java
Kartik Shah
Ranch Hand

Joined: Dec 07, 2000
Posts: 102
For level more than two levels of nesting I think it is better to use switch statement. However, properly constructed if statement can also be used. By saying PROPERLY CONSTRUCTED I mean to say we need to put the condition which we know would be encountered frequently. For example
if( x < 0)
// occurs 2 out of 10 times
else if( x = 0)
// occurs 3 out of 10 times
else
// occurs 5 out of 10 times
We should properly construct if statement so that the frequently occuring test case is kept first. Otherwise, here we are inviting two comparision overhead.
It is better to use switch statement in the case we can not predict the flow. However we would not like to spend so much time on analysing which is the most frequent case. It is rather better to use switch statement if the nesting more deeper.
Besides, switch statement gives you more modular approach. Consider
if (cond1)
{
// lots and lots of code goes here
}else if (cond2)
{
// lots ans lots of code goes down here also
}else
{
//lots and lots of code goes down here
}
It is better to use
switch( cond)
{
case 1: lotsofcode1();break;
case 2: lotsofcode2();break;
default: lotsofcode3();
}

Kartik Shah
SCJP, SCDJWS, IBM Certified Websphere & XML, PMP & Six Sigma - http://blog.kartikshah.info
Mark Herschberg
Sheriff

Joined: Dec 04, 2000
Posts: 6037
Along these lines, here's a question I've always wondered about.
When I did some assembly a number of years ago, on a simple processor, the only checking instructions supported by the chip was to see if a value was >, <, or = to 0 (zero). When code asked to see if A was greater than B, it actually checked to see if (A-B) was greater than 0.
- Is this true of pentiums and other chips today?
- If so, do compilers/JVMs still do what I described above?
- If so, then do FOR loops give fater performance when counting down, instead of counting up, in the cases of i=0..x? (I'm pretty sure compilers and JITs usually cannot figure out when it is safe to re-order an entire loop, right? Although interestingly they can figure out tail recursion.)

--Mark
hershey@vaultus.com
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Performance issues in decision blocks
 
Similar Threads
Can I distinguish JButtons?
switch question
Struts
Struts problem
OutOfBoundsException