performance - How deep should a try-catch block be in Java? -
due new job have work lot java , getting tiny details now. java code exceptions extent. wondering:
does calling stack effect performance of try-catch block lot? i.e. should avoid try around function calls function that... , goes deep?
i read try-catch blocks affect performance on exception. however, matter of far bubble up?
let's measure it, shall we?
package tools.bench; import java.math.bigdecimal; public abstract class benchmark { final string name; public benchmark(string name) { this.name = name; } abstract int run(int iterations) throws throwable; private bigdecimal time() { try { int nexti = 1; int i; long duration; { = nexti; long start = system.nanotime(); run(i); duration = system.nanotime() - start; nexti = (i << 1) | 1; } while (duration < 1000000000 && nexti > 0); return new bigdecimal((duration) * 1000 / i).movepointleft(3); } catch (throwable e) { throw new runtimeexception(e); } } @override public string tostring() { return name + "\t" + time() + " ns"; } enum exceptionstrategy { none { @override void run() { // nothing } }, normal { @override void run() { throw new runtimeexception(); } }, withoutstacktrace { @override void run() { throw new runtimeexception() { public synchronized throwable fillinstacktrace() { return this; }; }; } }; abstract void run(); } private static benchmark trybenchmark(final int depth, final exceptionstrategy strat) { return new benchmark("try, depth = " + depth + ", " + strat) { @override int run(int iterations) { int x = 0; (int = 1; < iterations; i++) { try { x += recurseandthrow(depth); } catch (exception e) { x++; } } return x; } private int recurseandthrow(int i) { if (i > 0) { return recurseandthrow(i - 1) + 1; } else { strat.run(); return 0; } } }; } public static void main(string[] args) throws exception { int[] depths = {1, 10, 100, 1000, 10000}; (int depth : depths) { (exceptionstrategy strat : exceptionstrategy.values()) { system.out.println(trybenchmark(depth, strat)); } } } }
on (quite dated) notebook, prints:
try, depth = 1, none 5.153 ns try, depth = 1, normal 3374.113 ns try, depth = 1, withoutstacktrace 602.570 ns try, depth = 10, none 59.019 ns try, depth = 10, normal 9064.392 ns try, depth = 10, withoutstacktrace 3528.987 ns try, depth = 100, none 604.828 ns try, depth = 100, normal 49387.143 ns try, depth = 100, withoutstacktrace 27968.674 ns try, depth = 1000, none 5388.270 ns try, depth = 1000, normal 457158.668 ns try, depth = 1000, withoutstacktrace 271881.336 ns try, depth = 10000, none 69793.242 ns try, depth = 10000, normal 2895133.943 ns try, depth = 10000, withoutstacktrace 2728533.381 ns
obviously, specific results vary hardware, , jvm implementation , configuration. however, general pattern remain same.
conclusions:
- the try statement incurs negligible overhead.
- throwing exception , unwinding callstack incurs overhead linear in size of stack (or amount of stack unwind).
- for stack sizes of real-world applications (let's assume 100 stack frames), overhead 50 micro seconds, or 0.00005 seconds.
- that overhead can reduced throwing exceptions without stack trace
recommendatations:
- don't worry performance of try statements.
- don't use exceptions signal conditions occur (say, more 1000 times per second).
- otherwise, don't worry performance of throwing exceptions.
- also, "premature optimization root of evil" ;-)
Comments
Post a Comment