The Artima Developer Community
Sponsored Link

Exceptions and Performance

Advertisement

Advertisement

This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002. If you wish to participate in discussions, please visit the new Artima Forums.

Message:

Exceptions and Performance

Posted by Bill Venners on 09 Jul 1998, 10:50 AM

> So even if myObj != null 99.999% of the time, checking for
> myObj == null is cheaper than setting up a try/catch block
> for myObj?
> I guess I could have run some performance tests for this one..

I was just reading through the reader comments for the
exceptions article at JavaWorld and a lot of people mentioned
that they wished I would have said something about the
performance implications of exceptions.

The funny thing was that some people said "the performance
costs of exceptions" and other people said "the performance
benefit of using exceptions." Well, that same dichotomy kind of
came out in this thread of discussion.

As Mike Manion mentioned, when an exception is thrown the JVM
has to do a lot more stuff than it has to do when a method
returns normally. It has to look through the method's
exception table for a matching catch clause, and if none is
found, it has to pop the stack and rethrow the exception one
stack frame down, where it has to check through the exception
table again. So a method completing normally is more "efficient"
than a method completing abruptly by throwing an exception.

On the other hand, Bryan Boone pointed out that if most of the
time the method won't throw the exception, then having some
condition be signaled by a thrown exception could end up being
more efficient. Somebody who posted to the JavaWorld reader
feedback mentioned that if you have a loop that executes 10000
times, it can be more efficient to wait for an exception to
be thrown to indicate a loop termination condition (say EOF)
than to invoke a method each pass through the loop to check
for the termination condition.

But every time I get on this topic of performance, I feel the
urge to jump up on a desk and yell: Don't do premature
optimization! You guys are probably already well aware of this
guiding principle, but just for the heck of it, here's my
philosophy in a nutshell:

When you are designing a class like Mike's Supplier class:


class Supplier
{
boolean canDoIt() {...}

void doIt() {...}
}

You should design it with flexibility in mind over performance,
because the odds are that this class won't be critical to
the actual performance of your application. (Because usually
only 10% to 20% of the code is performance-critical--executed
80* to 90% of the time.) So I would design it with a
canDoIt() method, as Mike recommends.

Then when I finish my program and realize I have a performance
problem, I would profile the program to identify the 10% to
20% of the code I need to worry about, then I'd just focus
on that code. I would try to use better algorithms, try to
make better uses of the APIs, apply standard techniques like
loop unrolling. Each time I tried something I would re-measure
the performance to see how I was doing and only keep
performance tweaks that made a difference. And only as a last
resort would I screw up my nice, flexible, object-oriented,
thread-safe design in the name of performance. And each time
I did that I would measure to see if my uglifying of the code
in the name of performance actually bought me better
performance.

Whew! I feel better now that I got that out.

So I think the answer to Bryan's original question is: it
depends. If I were to go through all the above steps and
end up finding that the doit1() method of Bryan's MyClass
was the heart of my performance bottleneck:


class MyClass {
MyObject myObj;
...
...
void doit1() {
if(myObj == null) {
myObj = new MyObject();
}
myObj.process();
}

void doit2() {
try {
myObj.process();
}
catch(NullPointerException e) {
myObj = new MyObject();
myObj.process();
}
}
}

I would be inclined to try and change doit1() to use doit2()'s
approach. Because if this thing really is in the performance-
critical part of the code, it is probably being called again
and again and again and again, so many times that most of the
time the myObj reference actually isn't null. So most of the
time the exception probably isn't being thrown. So I'd be
willing to try it.

BUT, I would measure the performance again after I changed
doit1() into doit2(), to see if I really got results. If I
didn't achieve satisfactory results, I'd change it back to
just checking for null explicitly, because I think that is
the more flexible (in this case, easier to read) way to
write this code.

bv



Replies:

Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2009 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us