by BehindJava
How exception handling effects the performance in Java
In this blog, we are going to see how exception handling effects the performance in Java with an example and you can try it yourself. It may vary from the system to system due to the hardware differences.
Exceptions should definitely NOT be used for anything that’s called frequently. Throwing a thousands of exceptions a second would cause a huge bottle neck. From JVM 1.5, using exceptions was 2x slower. On an average Execution time on a trivially small method more than tripled (3x) with exceptions. A trivially small loop that had to catch the exception saw a 2x increase in self-time.
Java exceptions under various combinations and conditions:
- Newly created exceptions vs pre-created exceptions
- Stack trace enabled vs disabled
- Stack trace requested vs never requested
- Caught at the top level vs re-thrown at every level vs chained/wrapped at every level
- Various levels of Java call stack depth
- No inlining optimizations vs extreme inlining vs default settings
- User-defined fields read vs not read
public class BehindJava {
int value;
public int getValue() {
return value;
}
public void reset() {
value = 0;
}
// Calculates without exception
public void method1(int i) {
value = ((value + i) / i) << 1;
// Will never be true
if ((i & 0xFFFFFFF) == 1000000000) {
System.out.println("You'll never see this!");
}
}
// Could in theory throw one, but never will
public void method2(int i) throws Exception {
value = ((value + i) / i) << 1;
// Will never be true
if ((i & 0xFFFFFFF) == 1000000000) {
throw new Exception();
}
}
// This one will regularly throw one
public void method3(int i) throws Exception {
value = ((value + i) / i) << 1;
// i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
// an AND operation between two integers. The size of the number plays
// no role. AND on 32 BIT always ANDs all 32 bits
if ((i & 0x1) == 1) {
throw new Exception();
}
}
public static void main(String[] args) {
int i;
long l;
BehindJava bj = new BehindJava();
l = System.currentTimeMillis();
t.reset();
for (i = 1; i < 100000000; i++) {
t.method1(i);
}
l = System.currentTimeMillis() - l;
System.out.println("method1 took " + l + " ms, result was " + t.getValue());
l = System.currentTimeMillis();
t.reset();
for (i = 1; i < 100000000; i++) {
try {
t.method2(i);
} catch (Exception e) {
System.out.println("You'll never see this!");
}
}
l = System.currentTimeMillis() - l;
System.out.println("method2 took " + l + " ms, result was " + t.getValue());
l = System.currentTimeMillis();
t.reset();
for (i = 1; i < 100000000; i++) {
try {
t.method3(i);
} catch (Exception e) {
// Do nothing here, as we will get here
}
}
l = System.currentTimeMillis() - l;
System.out.println("method3 took " + l + " ms, result was " + t.getValue());
}
}
Output:
method1 took 1204 ms, result was 2
method2 took 1209 ms, result was 2
method3 took 45704 ms, result was 2