The Cost of try-catch Blocks with an Exception

- 136 - public static boolean try_catch_in_loopint repeat, Object[] o { Integer i[] = new Integer[3]; for int j = repeat; j 0; j-- { try { i[0] = Integer o[j+12]; i[1] = Integer o[j2]; i[2] = Integer o[j+22]; } catch Exception e {return true;} } return false; } } Running this test in various VMs results in a 10 increase in the time taken by the looped try- catch test relative to the nonlooped test for some VMs. See Table 6-1 . Table 6-1, Extra Cost of the Looped try-catch Test Relative to the Nonlooped try-catch Test VM 1.2 1.2 no JIT 1.3 HotSpot

1.0 1.1.6

Increase in time ~10 None ~10 ~10 None

6.1.2 The Cost of try-catch Blocks with an Exception

Throwing an exception and executing the catch block has a significant overhead. This overhead seems to be due mainly to the cost of getting a snapshot of the stack when the exception is created the snapshot allows the stack trace to be printed. The cost is large: exceptions should not be thrown as part of the normal code path of your application unless you have factored it in. Generating exceptions is one place where good design and performance go hand in hand. You should throw an exception only when the condition is truly exceptional. For example, an end-of-file condition is not an exceptional condition all files end unless the end-of-file occurs when more bytes are expected. [1] Generally, the performance cost of throwing an exception is equivalent to several hundred lines of simple code executions. [1] There are exceptions to the rule. For example, in Section 7.2 , the cost of one exception thrown is less than the cost of repeatedly making a test in the loop, though this is seen only if the number of loop iterations is large enough. If your application is implemented to throw an exception during the normal flow of the program, you must not avoid the exception during performance tests. Any time costs coming from throwing exceptions must be included in performance testing, or the test results will be skewed from the actual performance of the application after deployment. To find the cost of throwing an exception, compare two ways of testing whether an object is a member of a class: trying a cast and catching the exception if the cast fails, versus using instanceof . In the code that follows, I have highlighted the lines that run the alternative tests: package tuning.exception; public class TryCatchCostTest { public static void mainString[] args { Integer i = new Integer3; - 137 - Boolean b = new Booleantrue; int REPEAT = 5000000; int FACTOR = 1000; boolean res; long time = System.currentTimeMillis ; for int j = REPEATFACTOR; j 0 ; j-- res = test1i; time = System.currentTimeMillis - time; System.out.printlntest1i took + time; time = System.currentTimeMillis ; for int j = REPEAT; j 0 ; j-- res = test1b; time = System.currentTimeMillis - time; System.out.printlntest1b took + time; and the same timed test for test2i and test2b, iterating REPEATFACTOR times ... } public static boolean test1Object o { try { Integer i = Integer o; return false; } catch Exception e {return true;} } public static boolean test2Object o { if o instanceof Integer return false; else return true; } } The results of this comparison show that if test2 using instanceof takes one time unit, t est1 with the ClassCastException thrown takes over 5000 time units in JDK 1.2 see Table 6-2 . On this time scale, test1 without the exception thrown takes eight time units: this time reflects the cost of making the cast and assignment. You can take the eight time units as the base time to compare exactly the same method executing with two different instances passed to it. Even for this comparison, the cost of executing test1 with an instance of the wrong type where the exception is thrown is at least 600 times more expensive than when the instance passed is of the right type. Table 6-2, Extra Cost of try-catch Blocks When Exceptions Are Thrown Relative Times for 1.2

1.2 no JIT 1.3