Performance of null tests?

A

Adam

I've just been having a discussion with a colleague and would be
interested to hear people's opinions on which of the below code
snippets would have the highest performance overhead.

Assume that <do good stuff> would throw a NullPointerException if
badger was null.

(A)

if(badger == null) {
<do bad stuff>
} else {
<do good stuff>
}

(B)

try {
<do good stuff>
} catch (NullPointerException npe) {
<do bad stuff>
}


All help appreciated!
Adam
 
V

VisionSet

Adam said:
I've just been having a discussion with a colleague and would be
interested to hear people's opinions on which of the below code
snippets would have the highest performance overhead.

Assume that <do good stuff> would throw a NullPointerException if
badger was null.

(A)

if(badger == null) {
<do bad stuff>
} else {
<do good stuff>
}

(B)

try {
<do good stuff>
} catch (NullPointerException npe) {
<do bad stuff>
}

If badger is truly exceptionally null then (B) will be best because there is
no conditional to test and there will rarely be any overhead of throwing the
exception.
On the other hand if badger is often null then (A) would be better since
testing for null is very low overhead. Whilst throwing an exception is high
overhead.
 
M

Michael Borgwardt

Adam said:
I've just been having a discussion with a colleague and would be
interested to hear people's opinions on which of the below code
snippets would have the highest performance overhead.

Answer: forget about premature optimization, write clean, understandable code.
Using exceptions for control flow is BAD style.
 
J

Jacob

Adam said:
(A)

if(badger == null) {
<do bad stuff>
} else {
<do good stuff>
}

(B)

try {
<do good stuff>
} catch (NullPointerException npe) {
<do bad stuff>
}

Hopefully this is an academic discussion only?

No matter what result you get from you performance
study, NEVER EVER write your code as in (B).
 
V

VisionSet

VisionSet said:
If badger is truly exceptionally null then (B) will be best because there is
no conditional to test and there will rarely be any overhead of throwing the
exception.
On the other hand if badger is often null then (A) would be better since
testing for null is very low overhead. Whilst throwing an exception is high
overhead.

Of course taking the wider perspective with performance aside, you should
write code in such a way as to never need to catch RuntimeExceptions (eg
NPE) at all. Checks such as (A) should be made to check for null where
necessary and if at all possible disallow nulls as a precondition to a
method by documenting and explicitly throwing NPE early.
 
C

Chris Smith

Jacob said:
Hopefully this is an academic discussion only?

No matter what result you get from you performance
study, NEVER EVER write your code as in (B).

Agreed that there is no reasonable circumstance where you'd cause a
NullPointerException to be thrown and then catch it again in the same
method. However, the general concept of choosing to allow
NullPointerException to occur is a good one when the null input is not
expected.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
B

Boudewijn Dijkstra

VisionSet said:
If badger is truly exceptionally null then (B) will be best because
there is no conditional to test and there will rarely be any overhead
of throwing the exception.
On the other hand if badger is often null then (A) would be better
since testing for null is very low overhead. Whilst throwing an
exception is high overhead.

In other words: it depends. It depends on the chance of an exception occuring
and the performance difference between the approaches.
 
E

Eric Sosman

Boudewijn said:
In other words: it depends. It depends on the chance of an exception occuring
and the performance difference between the approaches.

The `if' will probably turn into just a few instructions
once the JIT gets through with it -- ten instructions seems
high, but let's just suppose it's ten. We're working on the
back of the envelope here, okay?

Creating and catching the exception will take a variable
amount of work depending on how deep the stack happens to be,
but let's be optimistic and suppose it takes only ten thousand
instructions, including the eventual cost of garbage collecting
the NullPointerException object after it's been discarded.

Under these suppositions, one exception carries the time
penalty of a thousand `if' tests. Using an exception to avoid
the `if' would be a win if the reference is null less than one
thousandth of the time, non-null more than 99.9% of the time.

How much of a gain can you get? Let's suppose the reference
is null just one ten-thousandth of the time, one tenth of the
break-even point. If the code executes a million times, you'll
throw one hundred exceptions at a (supposed) cost of one million
instructions. Meanwhile, you've avoided (supposedly) ten million
instructions for the `if' tests you didn't make. The gain is
nine million instructions, which sounds pretty good.

But how good is it, really? Well, processors vary and
caches vary and memory speeds vary and blah blah blah, but
let's be pessimistic and assume you can execute instructions
at a rate of only 1GHz. You have saved nine milliseconds.

Nine whole milliseconds.

nine
thousandths
of
one
second

You have klutzed up your code, and even under the most
optimistic assumptions imaginable a million executions of
the "optimized" version have saved you

nine
thousandths
of
one
second

That's roughly the amount of time between successive
wave crests of the note on the bottom line of the bass clef,
two octaves below concert A.

nine
thousandths
of
one
second

It's about two-thirds the time of one CRT refresh.

nine
thousandths
of
one
second

It's enough time for a race car going 200 miles/hour
to travel thirty-two inches.

nine
thousandths
of
one
second

Let me ask you this: What are you going to do with all
that extra time? Won't it hang heavy on your hands?
 
C

Chris Uppal

Eric said:
Let me ask you this: What are you going to do with all
that extra time? Won't it hang heavy on your hands?

Beautifully put (including the rest that I snipped).

I think part of the problem is that we daily use machines that expend /HUGE/
amounts of processing power to do even the simplest of tasks (I'd hate to know
how long the execution path is for pressing one key in OE as I type this; and I
shudder to think what the code path is like for clicking a button in Eclipse --
it must be in 100's of millions to billions range, judging by the treacly way
it responds). One effect of that is that we forget how frighteningly fast our
machines are.

It makes it difficult to form (or maintain) an intuitive sense of what's cheap
and what's expensive -- or a usefully accurate one anyway.

"Wanna save a second ? OK which /billion/ instructions are you not going to
execute ?"

-- chris
 
A

Adam

Wow - that's a lot of responses, cheers everyone!

That is what I suspected and our next step will be to evaluate a load
of different points in the code with this in mind. Based on the
likelihood of a null scenario!

Just to give a bit of context, this is part of a server side method
called heavily by a multitude of clients - ergo performance is
paramount, easily readable code can be sacrificied (but mitigated with
verbose comments, one hopes).

And no, I'm not a student ;)
 
S

steve

Wow - that's a lot of responses, cheers everyone!

That is what I suspected and our next step will be to evaluate a load
of different points in the code with this in mind. Based on the
likelihood of a null scenario!

Just to give a bit of context, this is part of a server side method
called heavily by a multitude of clients - ergo performance is
paramount, easily readable code can be sacrificied (but mitigated with
verbose comments, one hopes).

And no, I'm not a student ;)

For good code design you should not be using exceptions , to do "if",
"while","case" processing.

There is a very good article on the sun java site , called ( i think) "use &
abuse of exceptions"
Your "use" sun classes as serious "abuse", but they also go indepth as to
why you should not do it (giving timings etc. basically when you cause an
exception you are creating an object each time it occurs), and it is very
expensive in time.

Finally if it is server side code ( and considering your user load) ,
consider , the operation of generating thousands of exceptions, both on
memory & time.
Eeeewwwww!!. :)

steve
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top