TL;DR;
Exceptions are for cases when things go wrong, using them to assist normal code flow
is not ok. It will cause performance problems and your cat will eat you alive.
Intro
Okay, exceptions are exceptional (captain_obvious.jpeg), lots of people against using them to control normal flow so on, so forth. However, the last thing I wanna be is one of these guys:
"Exceptions are bad! I've read about it in a blog yesterday. Everyone stop using em. NOW!!!11" Anonymous passionate programmer
We're not like this here ;) Let's dive into how things are made.
Purpose Determines Design
Exception is a way to tell jvm: "I can't continue. Maak it stap!". Such Occasions are rare. Like if you got NullPointerException you don't care about performance, you care about logging stacktrace.
On bytecode level it works in a following way.
an object of Throwable type is constructed when exception is created, stacktrace is collected. This means that all optimizations will be unoptimized, jit compilation uncompiled, and the whole thread stopped, while jvm traverses frames up the stack.
athrow is called with object being on a stack athrow searches for appropriate exception handler (each method could have zero or more exception handlers) to determine if vm should goto catch block or drop the stack.
If you want more info on how exceptions work on a low-level. JLS is to the rescue. But for now the important part is that price is hidden in creation of exception and not in throwing it. Also since we need to traverse stack upwards throwing exceptions is more expensive the bigger stack trace is.
Measurements
Talking about performance is pointless without measuring it. So here's a test code that has been used for it. So let's see what we've got!
First of all let's compare throwing exceptions and if/else branch.
Exceptions are slower, throughput is 70-160 times lower (sic!). So slower we need a second graph to see how exceptions perform as stack deepens.
Almost linear drop in throughput justifies that exceptions are O(N) when it comes to stack depth.
How to spot
1. connect with JMC and it will give you a warning if there are too many exceptions
2. disable exception stack trace generation (see following part) and check if performance has been improved.
How to Fix
Proper fix for this case is to refactor and stop exception abuse.
Not-so proper fix could mean disabling stack trace generation either in jvm parameter,
or by overriding appropriate method in exception.
Yes you will lose stack trace information in this case, but the fix is quick and it will work faster.
It's kind of playing with fire, but the choice is yours ;).
[1]: Effective java Chapter 9: Exceptions.
[2]: Java: The Good Parts by jim Waldo (3. exceptions. Use and abuse)
Comments